diff --git a/changelog.md b/changelog.md index c8431a4a..f8a08514 100644 --- a/changelog.md +++ b/changelog.md @@ -1,5 +1,23 @@ # CHANGELOG +## 3.0.0 +CHANGED: +- (breaking) Updated OSRM to 6.0.0 +- Dockerfile now uses Node 24.12 on debian trixie +- Valhalla source now uses JS binding instead of child process + +UPDATED: +- Updated all package.json dependencies to last versions (08/01/2026) +- Updated default docker image and the associated doc +- Updated the sample docker config to have empty dirs +- Enforced resource files to end with .resource and source files to end with .source + +FIXED: +- Link to openApi in simple api was redirecting to osrm Api + +REMOVED: +- All references to Smartrouting and Smartpgr + ## 2.3.1 FIXED: - invalid isochrone geometries diff --git a/docker/config/resources/.gitkeep b/docker/config/resources/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/docker/config/service.json b/docker/config/service.json index 9789f962..3e15af54 100644 --- a/docker/config/service.json +++ b/docker/config/service.json @@ -34,16 +34,6 @@ "https": "false", "host": "0.0.0.0", "port": "8080" - }, - { - "id": "externalServer", - "https": "true", - "host": "0.0.0.0", - "port": "443", - "options": { - "key": "/run/secrets/key", - "cert": "/run/secrets/cert" - } } ], "cors": { diff --git a/docker/config/sources/.gitkeep b/docker/config/sources/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/docker/distributions/debian/Dockerfile b/docker/distributions/debian/Dockerfile index 9b69b86c..85e5ed60 100644 --- a/docker/distributions/debian/Dockerfile +++ b/docker/distributions/debian/Dockerfile @@ -1,10 +1,7 @@ -### TODO : Supprimer la compilation et l'installation de Valhalla dès que l'on aura un binding NodeJS pour lui et donc repasser sur une image node -FROM ghcr.io/valhalla/valhalla@sha256:6fb108a960bdc63c12b1c92ab04517a0c56a019ef45c9b9c8cf847d8de9db72b +FROM node:24.12-trixie-slim -### Mise à jour des +### Mise à jour des paquets RUN apt-get update && apt-get upgrade -y -RUN curl -fsSL https://deb.nodesource.com/setup_16.x | bash - && \ - apt-get install -y nodejs ### Dossier contenant la configuration de Road2 WORKDIR /home/docker/config diff --git a/documentation/apis/simple/1.0.0/api.json b/documentation/apis/simple/1.0.0/api.json index 1783072a..348c722a 100644 --- a/documentation/apis/simple/1.0.0/api.json +++ b/documentation/apis/simple/1.0.0/api.json @@ -10,16 +10,8 @@ }, "servers": [ { - "url": "https://wxs.ign.fr/calcul/geoportail/itineraire/rest/1.0.0/", - "description": "Serveur de test IGN pour l'itinéraire" - }, - { - "url": "https://wxs.ign.fr/calcul/geoportail/isochrone/rest/1.0.0/", - "description": "Serveur de test IGN pour l'isochrone" - }, - { - "url": "http://localhost:8080/simple/1.0.0/", - "description": "Serveur de test local" + "url": "https://data.geopf.fr/navigation", + "description": "Géoplateforme" } ], "tags": [ diff --git a/documentation/configuration/resources/smartpgr.resource b/documentation/configuration/resources/smartpgr.resource deleted file mode 100644 index 605be704..00000000 --- a/documentation/configuration/resources/smartpgr.resource +++ /dev/null @@ -1,674 +0,0 @@ -{ - "resource": { - "id": "bduni-idf-smartpgr", - "type": "smartpgr", - "resourceVersion": "yyyy-mm-dd", - "threshold": 30000, - "description": "Donn\u00e9es BDUNI v2.", - "sources": [ - "bdtopo-smartrouting", - "bduni-idf-pgr" - ], - "availableOperations": [ - { - "id": "route", - "parameters": [ - { - "id": "resource", - "values": [ - "bduni-idf-smartpgr" - ] - }, - { - "id": "start", - "values": { - "bbox": "1.7,48.4,3.3,49.1", - "projection": "EPSG:4326" - } - }, - { - "id": "end", - "values": { - "bbox": "1.7,48.4,3.3,49.1", - "projection": "EPSG:4326" - } - }, - { - "id": "profile", - "defaultValueContent": "car", - "values": [ - "car", - "pedestrian" - ] - }, - { - "id": "optimization", - "defaultValueContent": "fastest", - "values": [ - "fastest", - "shortest" - ] - }, - { - "id": "intermediates", - "values": { - "bbox": "1.7,48.4,3.3,49.1", - "projection": "EPSG:4326" - } - }, - { - "id": "getSteps", - "defaultValueContent": "true" - }, - { - "id": "waysAttributes", - "values": [ - "nom_1_gauche", - "nom_1_droite", - "cpx_numero", - "cpx_toponyme_route_nommee", - "cleabs", - "nature", - "importance", - "position_par_rapport_au_sol", - "nombre_de_voies", - "largeur_de_chaussee", - "itineraire_vert", - "sens_de_circulation", - "bande_cyclable", - "reserve_aux_bus", - "urbain", - "vitesse_moyenne_vl", - "acces_vehicule_leger", - "acces_pieton", - "nature_de_la_restriction", - "restriction_de_hauteur", - "restriction_de_poids_total", - "restriction_de_poids_par_essieu", - "restriction_de_largeur", - "restriction_de_longueur", - "matieres_dangereuses_interdites", - "insee_commune_gauche", - "insee_commune_droite", - "cpx_numero_route_europeenne", - "cpx_classement_administratif", - "cpx_gestionnaire" - ] - }, - { - "id": "geometryFormat", - "defaultValueContent": "geojson", - "values": [ - "geojson", - "polyline", - "wkt" - ] - }, - { - "id": "bbox", - "defaultValueContent": "true" - }, - { - "id": "projection", - "defaultValueContent": "EPSG:4326", - "values": [ - "EPSG:4326", - "EPSG:2154" - ] - }, - { - "id": "timeUnit", - "defaultValueContent": "minute", - "values": [ - "hour", - "minute", - "second", - "standard" - ] - }, - { - "id": "distanceUnit", - "defaultValueContent": "meter", - "values": [ - "meter", - "kilometer" - ] - }, - { - "id": "constraints", - "defaultPreferredCostRatio": 0.8, - "defaultAvoidCostRatio": 1.2, - "values": [ - { - "keyType": "name-pgr", - "key": "wayType", - "availableConstraintType": [ - "banned" - ], - "availableValues": [ - { - "value": "autoroute", - "field": "acces_vehicule_leger", - "condition": { - "type": "equal", - "value": "$niv4$A p\u00e9age$niv4$" - } - }, - { - "value": "tunnel", - "field": "position_par_rapport_au_sol", - "condition": { - "type": "less", - "value": "0" - } - }, - { - "value": "pont", - "field": "position_par_rapport_au_sol", - "condition": { - "type": "greater", - "value": "0" - } - } - ] - }, - { - "keyType": "numerical-pgr", - "key": "largeur", - "availableConstraintType": [ - "banned" - ], - "field": "largeur_de_chaussee" - }, - { - "keyType": "numerical-pgr", - "key": "importance", - "availableConstraintType": [ - "banned", - "avoid", - "prefer" - ], - "field": "importance" - }, - { - "keyType": "name-pgr", - "key": "nature", - "availableConstraintType": [ - "banned" - ], - "availableValues": [ - { - "value": "sentier", - "field": "nature", - "condition": { - "type": "equal", - "value": "$niv4$Sentier$niv4$" - } - }, - { - "value": "bac_ou_liaison_maritime", - "field": "nature", - "condition": { - "type": "equal", - "value": "$niv4$Bac ou liaison maritime$niv4$" - } - }, - { - "value": "bretelle", - "field": "nature", - "condition": { - "type": "equal", - "value": "$niv4$Bretelle$niv4$" - } - }, - { - "value": "chemin", - "field": "nature", - "condition": { - "type": "equal", - "value": "$niv4$Chemin$niv4$" - } - }, - { - "value": "escalier", - "field": "nature", - "condition": { - "type": "equal", - "value": "$niv4$Escalier$niv4$" - } - }, - { - "value": "piste_cyclable", - "field": "nature", - "condition": { - "type": "equal", - "value": "$niv4$Piste cyclable$niv4$" - } - }, - { - "value": "rond-point", - "field": "nature", - "condition": { - "type": "equal", - "value": "$niv4$Rond-point$niv4$" - } - }, - { - "value": "route_a_1_chaussee", - "field": "nature", - "condition": { - "type": "equal", - "value": "$niv4$Route \u00e0 1 chauss\u00e9e$niv4$" - } - }, - { - "value": "route_a_2_chaussees", - "field": "nature", - "condition": { - "type": "equal", - "value": "$niv4$Route \u00e0 2 chauss\u00e9es$niv4$" - } - }, - { - "value": "route_empierree", - "field": "nature", - "condition": { - "type": "equal", - "value": "$niv4$Route empierr\u00e9e$niv4$" - } - }, - { - "value": "type_autoroutier", - "field": "nature", - "condition": { - "type": "equal", - "value": "$niv4$Type autoroutier$niv4$" - } - } - ] - }, - { - "keyType": "name-pgr", - "key": "cpx_classement_administratif", - "availableConstraintType": [ - "banned", - "prefer", - "avoid" - ], - "availableValues": [ - { - "value": "vide", - "field": "cpx_classement_administratif", - "condition": { - "type": "equal", - "value": "$niv4$$niv4$" - } - }, - { - "value": "autoroute", - "field": "cpx_classement_administratif", - "condition": { - "type": "like", - "value": "$niv4$%Autoroute%$niv4$" - } - }, - { - "value": "nationale", - "field": "cpx_classement_administratif", - "condition": { - "type": "equal", - "value": "$niv4$Nationale$niv4$" - } - }, - { - "value": "departementale", - "field": "cpx_classement_administratif", - "condition": { - "type": "equal", - "value": "$niv4$D\u00e9partementale$niv4$" - } - }, - { - "value": "voie_communale", - "field": "cpx_classement_administratif", - "condition": { - "type": "equal", - "value": "$niv4$Voie communale$niv4$" - } - }, - { - "value": "chemin_rural", - "field": "cpx_classement_administratif", - "condition": { - "type": "equal", - "value": "$niv4$Chemin rural$niv4$" - } - } - ] - } - ] - } - ] - }, - { - "id": "isochrone", - "parameters": [ - { - "id": "resource", - "values": [ - "bduni-idf-smartpgr" - ] - }, - { - "id": "point", - "values": { - "bbox": "1.7,48.4,3.3,49.1", - "projection": "EPSG:4326" - } - }, - { - "id": "costType", - "defaultValueContent": "time", - "values": [ - "time", - "distance" - ] - }, - { - "id": "costValue", - "values": { - "min": 1 - } - }, - { - "id": "profile", - "defaultValueContent": "car", - "values": [ - "car", - "pedestrian" - ] - }, - { - "id": "direction", - "defaultValueContent": "departure", - "values": [ - "departure", - "arrival" - ] - }, - { - "id": "projection", - "defaultValueContent": "EPSG:4326", - "values": [ - "EPSG:4326", - "EPSG:2154", - "EPSG:4559", - "EPSG:2972", - "EPSG:2975", - "EPSG:4471", - "EPSG:3857" - ] - }, - { - "id": "geometryFormat", - "defaultValueContent": "geojson", - "values": [ - "geojson", - "polyline", - "wkt" - ] - }, - { - "id": "timeUnit", - "defaultValueContent": "second", - "values": [ - "hour", - "minute", - "second" - ] - }, - { - "id": "distanceUnit", - "defaultValueContent": "meter", - "values": [ - "meter", - "kilometer" - ] - }, - { - "id": "constraints", - "values": [ - { - "keyType": "name-pgr", - "key": "wayType", - "availableConstraintType": [ - "banned" - ], - "availableValues": [ - { - "value": "autoroute", - "field": "acces_vehicule_leger", - "condition": { - "type": "equal", - "value": "$niv3$A p\u00e9age$niv3$" - } - }, - { - "value": "tunnel", - "field": "position_par_rapport_au_sol", - "condition": { - "type": "less", - "value": "0" - } - }, - { - "value": "pont", - "field": "position_par_rapport_au_sol", - "condition": { - "type": "greater", - "value": "0" - } - } - ] - }, - { - "keyType": "numerical-pgr", - "key": "LARGEUR", - "availableConstraintType": [ - "banned" - ], - "field": "largeur_de_chaussee" - }, - { - "keyType": "numerical-pgr", - "key": "IMPORTANCE", - "availableConstraintType": [ - "banned" - ], - "field": "importance" - }, - { - "keyType": "name-pgr", - "key": "RESTR_MAT", - "availableConstraintType": [ - "banned" - ], - "availableValues": [ - { - "value": "vrai", - "field": "matieres_dangereuses_interdites", - "condition": { - "type": "equal", - "value": "true" - } - }, - { - "value": "faux", - "field": "matieres_dangereuses_interdites", - "condition": { - "type": "equal", - "value": "false" - } - } - ] - }, - { - "keyType": "name-pgr", - "key": "NATURE", - "availableConstraintType": [ - "banned" - ], - "availableValues": [ - { - "value": "sentier", - "field": "nature", - "condition": { - "type": "equal", - "value": "$niv4$Sentier$niv4$" - } - }, - { - "value": "bac_ou_liaison_maritime", - "field": "nature", - "condition": { - "type": "equal", - "value": "$niv4$Bac ou liaison maritime$niv4$" - } - }, - { - "value": "bretelle", - "field": "nature", - "condition": { - "type": "equal", - "value": "$niv4$Bretelle$niv4$" - } - }, - { - "value": "chemin", - "field": "nature", - "condition": { - "type": "equal", - "value": "$niv4$Chemin$niv4$" - } - }, - { - "value": "escalier", - "field": "nature", - "condition": { - "type": "equal", - "value": "$niv4$Escalier$niv4$" - } - }, - { - "value": "piste_cyclable", - "field": "nature", - "condition": { - "type": "equal", - "value": "$niv4$Piste cyclable$niv4$" - } - }, - { - "value": "rond-point", - "field": "nature", - "condition": { - "type": "equal", - "value": "$niv4$Rond-point$niv4$" - } - }, - { - "value": "route_a_1_chaussee", - "field": "nature", - "condition": { - "type": "equal", - "value": "$niv4$Route \u00e0 1 chauss\u00e9e$niv4$" - } - }, - { - "value": "route_a_2_chaussees", - "field": "nature", - "condition": { - "type": "equal", - "value": "$niv4$Route \u00e0 2 chauss\u00e9es$niv4$" - } - }, - { - "value": "route_empierree", - "field": "nature", - "condition": { - "type": "equal", - "value": "$niv4$Route empierr\u00e9e$niv4$" - } - }, - { - "value": "type_autoroutier", - "field": "nature", - "condition": { - "type": "equal", - "value": "$niv4$Type autoroutier$niv4$" - } - } - ] - }, - { - "keyType": "name-pgr", - "key": "CL_ADMIN", - "availableConstraintType": [ - "banned" - ], - "availableValues": [ - { - "value": "vide", - "field": "cpx_classement_administratif", - "condition": { - "type": "equal", - "value": "$niv4$$niv4$" - } - }, - { - "value": "autoroute", - "field": "cpx_classement_administratif", - "condition": { - "type": "like", - "value": "$niv3$%Autoroute%$niv3$" - } - }, - { - "value": "nationale", - "field": "cpx_classement_administratif", - "condition": { - "type": "equal", - "value": "$niv3$Nationale$niv3$" - } - }, - { - "value": "departementale", - "field": "cpx_classement_administratif", - "condition": { - "type": "equal", - "value": "$niv3$D\u00e9partementale$niv3$" - } - }, - { - "value": "voie_communale", - "field": "cpx_classement_administratif", - "condition": { - "type": "equal", - "value": "$niv3$Voie communale$niv3$" - } - }, - { - "value": "chemin_rural", - "field": "cpx_classement_administratif", - "condition": { - "type": "equal", - "value": "$niv3$Chemin rural$niv3$" - } - } - ] - } - ] - } - ] - } - ] - } diff --git a/documentation/configuration/sources/smartrouting.source b/documentation/configuration/sources/smartrouting.source deleted file mode 100644 index 3bdee18e..00000000 --- a/documentation/configuration/sources/smartrouting.source +++ /dev/null @@ -1,10 +0,0 @@ -{ - "id": "bdtopo-smartrouting", - "type": "smartrouting", - "description":"test", - "projection": "EPSG:4326", - "bbox": "-180,-90,180,90", - "storage": { - "url": "https://wxs.ign.fr/calcul" - } -} diff --git a/documentation/configuration/sources/source_model.yaml b/documentation/configuration/sources/source_model.yaml index 3b4358f9..0e1f13c1 100644 --- a/documentation/configuration/sources/source_model.yaml +++ b/documentation/configuration/sources/source_model.yaml @@ -1,10 +1,10 @@ # Description d'un fichier de source pour Road2 -# id de la source, utile pour la charger une seule fois dans Road2. +# id de la source, utile pour la charger une seule fois dans Road2. "id": type: string required: true -# Description de la source +# Description de la source "description": type: string required: true @@ -12,7 +12,7 @@ "type": type: string required: true - enum: ["osrm","pgr","smartrouting","valhalla"] + enum: ["osrm","pgr","valhalla"] # Projection des données sources "projection": type: string @@ -20,13 +20,13 @@ # Bbox des données dans la projection précisée "bbox": type: string - required: true + required: true # Stockage de la source. Elle dépend de son type # TODO : finir de spécifier (en attendant, voir les exemples) "storage": type: object required: true -# Coûts calculés sur la topologie précisée précedemment. On peut en avoir plusieurs. +# Coûts calculés sur la topologie précisée précedemment. On peut en avoir plusieurs. # TODO : finir de spécifier (en attendant, regarder les exemples de fichier) "cost": type: object @@ -40,4 +40,3 @@ "optmization": type: string required: true - \ No newline at end of file diff --git a/documentation/docker/distributions/readme.md b/documentation/docker/distributions/readme.md index a114cb8f..f82db06d 100644 --- a/documentation/docker/distributions/readme.md +++ b/documentation/docker/distributions/readme.md @@ -12,7 +12,7 @@ docker build -t road2-debian -f docker/distributions/debian/Dockerfile . Pour lancer l'application, il suffit d'utiliser la commande suivante: ``` -docker run --name road2-debian-server --rm -d -p 8080:8080 road2-debian +docker run --name road2-debian-server --rm -d -p 8080:8080 -v ${PWD}/docker/config:/home/docker/config -v ${PWD}/docker/config:/home/docker/data road2-debian ``` ### Mode DEBUG diff --git a/package.json b/package.json index 6c5aea46..8f73fec8 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "road2", - "version": "2.2.8", + "version": "3.0.0", "description": "Calcul d'itinéraire", "author": "RDEV - IGN", "main": "src/js/road2.js", @@ -16,22 +16,23 @@ "debug": "env NODE_ENV=debug node --inspect=0.0.0.0:9229 ./src/js/road2.js" }, "dependencies": { - "@mapbox/polyline": "1.1.1", - "@turf/turf": "6.5.0", - "assert": "2.0.0", + "@mapbox/polyline": "1.2.1", + "@turf/turf": "7.3.0", + "assert": "2.1.0", "cors": "2.8.5", - "express": "4.18.2", - "got": "11.8.2", - "helmet": "6.0.1", - "https-proxy-agent": "5.0.1", - "log4js": "6.7.1", - "nconf": "0.12.0", - "proj4": "2.8.0", - "swagger-ui-express": "4.6.3" + "express": "5.2.1", + "got": "14.6.6", + "helmet": "8.1.0", + "https-proxy-agent": "7.0.6", + "log4js": "6.9.1", + "nconf": "0.13.0", + "proj4": "2.20.2", + "swagger-ui-express": "5.0.1" }, "optionalDependencies": { - "osrm": "5.26.0", - "pg": "8.9.0" + "@project-osrm/osrm": "26.4.1", + "pg": "8.16.3", + "@valhallajs/valhallajs": "3.7.0" }, "devDependencies": { "sinon": "^7.2.7", @@ -46,7 +47,8 @@ "express", "log4js", "nconf", - "osrm", + "@project-osrm/osrm", + "@valhallajs/valhallajs", "pg", "@mapbox/polyline", "@turf/turf", diff --git a/src/js/apis/osrm/1.0.0/index.js b/src/js/apis/osrm/1.0.0/index.js index 8e542452..f8c93b22 100644 --- a/src/js/apis/osrm/1.0.0/index.js +++ b/src/js/apis/osrm/1.0.0/index.js @@ -28,12 +28,12 @@ router.get('/openapi/swagger.json', (req, res) => { }); router.use( '/openapi', - swaggerUi.serve, - swaggerUi.setup(null, { + swaggerUi.serveFiles(null, { swaggerOptions: { url: '/osrm/1.0.0/openapi/swagger.json' } - }) + }), + swaggerUi.setup(swaggerDocument) ); // GetCapabilities diff --git a/src/js/apis/simple/1.0.0/index.js b/src/js/apis/simple/1.0.0/index.js index ed93d0ef..709d172f 100644 --- a/src/js/apis/simple/1.0.0/index.js +++ b/src/js/apis/simple/1.0.0/index.js @@ -61,12 +61,12 @@ router.get('/openapi/swagger.json', (req, res) => { }); router.use( '/openapi', - swaggerUi.serve, - swaggerUi.setup(null, { + swaggerUi.serveFiles(null, { swaggerOptions: { url: '/simple/1.0.0/openapi/swagger.json' } - }) + }), + swaggerUi.setup(swaggerDocument) ); // GetCapabilities diff --git a/src/js/resources/resourceManager.js b/src/js/resources/resourceManager.js index e07c2f9f..4a1acc11 100644 --- a/src/js/resources/resourceManager.js +++ b/src/js/resources/resourceManager.js @@ -4,7 +4,6 @@ const fs = require('fs'); const path = require('path'); const osrmResource = require('../resources/osrmResource'); const pgrResource = require('../resources/pgrResource'); -const smartpgrResource = require('../resources/smartpgrResource'); const valhallaResource = require('../resources/valhallaResource'); const log4js = require('log4js'); @@ -31,13 +30,12 @@ module.exports = class resourceManager { // Liste des ressources chargées dans le manager this._resource = {}; - // Correspondance entre les ressources et les opérations possibles + // Correspondance entre les ressources et les opérations possibles // Le contenu de ce tableau dépend du code écrit dans la ressource correspondante, de ce nous avons choisis de l'implémenter dans Road2 // Ce tableau peut beaucoup ressembler à son équivalent du sourceManager mais il peut aussi s'en écarter selon les futures ressources qui seront implémentées this._operationsByType = { "osrm": ["nearest", "route"], "pgr": ["route", "isochrone"], - "smartpgr": ["route", "isochrone"], "valhalla": ["route", "isochrone"] }; @@ -53,7 +51,7 @@ module.exports = class resourceManager { * * @function * @name get resource - * @description Récupérer les ressources + * @description Récupérer les ressources * */ get resource() { @@ -66,7 +64,7 @@ module.exports = class resourceManager { * @name checkResourceDirectory * @description Fonction utilisée pour vérifier le contenu d'un dossier de description d'une ressource. * @param {string} directory - Dossier qui contient les configurations des ressources - * @return {boolean} + * @return {boolean} * */ @@ -94,6 +92,10 @@ module.exports = class resourceManager { for (let i = 0; i < fileList.length; i++) { let resource = fileList[i]; + if (!resource.endsWith(".resource")) { + LOGGER.warn("Le fichier " + resource + " n'est pas un fichier de ressource (extension .resource) et ne sera pas vérifié."); + continue; + } let resourceFile = ""; try { resourceFile = directory + "/" + resource; @@ -104,7 +106,7 @@ module.exports = class resourceManager { let resourceConf = {}; try { - // Il s'agit juste de savoir si le fichier est lisible par Road2, il sera exploité plus tard + // Il s'agit juste de savoir si le fichier est lisible par Road2, il sera exploité plus tard resourceConf = JSON.parse(fs.readFileSync(resourceFile)); } catch (error) { LOGGER.error("Mauvaise configuration: impossible de lire ou de parser le fichier de ressource: " + resourceFile); @@ -137,7 +139,7 @@ module.exports = class resourceManager { * @name checkResourceConfiguration * @description Fonction utilisée pour vérifier le contenu d'un fichier de description d'une ressource. * @param {object} resourceJsonObject - Configuration de la ressource - * @return {boolean} + * @return {boolean} * */ @@ -214,7 +216,7 @@ module.exports = class resourceManager { LOGGER.info("Type de la ressource disponible: " + resourceJsonObject.resource.type); } else { LOGGER.error("La ressource indique un type invalide: " + resourceJsonObject.resource.type); - return false; + return false; } } @@ -296,13 +298,13 @@ module.exports = class resourceManager { * * @function * @name flushCheckedResource - * @description Vider la liste des ressources déjà vérifiées + * @description Vider la liste des ressources déjà vérifiées * */ flushCheckedResource() { this._checkedResourceId = new Array(); - + } /** @@ -311,7 +313,7 @@ module.exports = class resourceManager { * @name loadResourceDirectory * @description Fonction utilisée pour charger le contenu d'un dossier de description d'une ressource. * @param {string} directory - Dossier qui contient les configurations des ressources - * @return {boolean} + * @return {boolean} * */ @@ -356,7 +358,7 @@ module.exports = class resourceManager { * @name loadResourceConfiguration * @description Fonction utilisée pour créer une ressource à partir de sa configuration * @param {json} resourceJsonObject - Description JSON de la ressource - * @return {boolean} + * @return {boolean} * */ @@ -397,15 +399,13 @@ module.exports = class resourceManager { if (!this._operationManager.loadResourceOperationConfiguration(resourceOperationHash, resourceJsonObject)) { LOGGER.error("Erreur lors de la creation des operations de la ressource"); return false; - } + } // Création de la ressource if (resourceJsonObject.resource.type === "osrm") { resource = new osrmResource(resourceJsonObject, resourceOperationHash); } else if (resourceJsonObject.resource.type === "pgr") { resource = new pgrResource(resourceJsonObject, resourceOperationHash); - } else if (resourceJsonObject.resource.type === "smartpgr") { - resource = new smartpgrResource(resourceJsonObject, resourceOperationHash); } else if (resourceJsonObject.resource.type === "valhalla") { resource = new valhallaResource(resourceJsonObject, resourceOperationHash); } else { @@ -413,7 +413,7 @@ module.exports = class resourceManager { return false; } - // Initialisation de la correspondance entre ressource et sources + // Initialisation de la correspondance entre ressource et sources if (!resource.initResource(this._sourceManager)) { LOGGER.error("Impossible d'instancier les liens avec les sources"); return false; @@ -424,7 +424,7 @@ module.exports = class resourceManager { this._resource[resourceJsonObject.resource.id] = resource; return true; - + } diff --git a/src/js/resources/smartpgrResource.js b/src/js/resources/smartpgrResource.js deleted file mode 100644 index ddd50379..00000000 --- a/src/js/resources/smartpgrResource.js +++ /dev/null @@ -1,229 +0,0 @@ -'use strict'; - -const Resource = require('./resource'); -const log4js = require('log4js'); - -// Création du LOGGER -var LOGGER = log4js.getLogger("SMARTPGRRESOURCE"); - -/** -* -* @class -* @name pgrResource -* @description Classe modélisant une ressource pgRouting. -* -*/ - -module.exports = class smartpgrResource extends Resource { - - - /** - * - * @function - * @name constructor - * @description Constructeur de la classe pgrResource - * @param {json} resourceJsonObject - Description JSON de la ressource - * @param {object} operations - Objet contenant des instances de classes filles de ResourceOperation - * - */ - constructor(resourceJsonObject, operations) { - - // Constructeur parent - super(resourceJsonObject.resource.id,resourceJsonObject.resource.type, resourceJsonObject.resource.resourceVersion, operations); - - // Stockage de la configuration - this._configuration = resourceJsonObject.resource; - - // Seuils de switch entre les sources smartrouting et pgr - this._distThreshold; // en metres - this._timeThresholdCar; // en secondes - this._timeThresholdPedestrian; // en secondes - - // Correspondance entre profile/optimization et sourceId - this._linkedSource = {}; - - } - - /** - * - * @function - * @name get configuration - * @description Récupérer la configuration de la ressource - * - */ - get configuration () { - return this._configuration; - } - - /** - * - * @function - * @name initResource - * @description Créer les liens entre divers éléments d'une ressource et les sources associées - * Ce traitement est placé ici car c'est la ressource qui sait quelle source est concernée par la requête. - * @param {SourceManager} sourceManager - Manager des sources du service - * @return {boolean} - * - */ - initResource (sourceManager) { - - // Seuils de switch entre les sources smartrouting et pgr - this._distThreshold = this._configuration.threshold; // en metres - this._timeThresholdCar = (this._distThreshold / 130000) * 3600; // en secondes - this._timeThresholdPedestrian = (this._distThreshold / 4000) * 3600; // en secondes - - // Instanciation de la correspondance entre profile/optimization et sourceId - for (let i=0; i < this._configuration.sources.length; i++) { - - if (!sourceManager.isLoadedSourceAvailable(this._configuration.sources[i])) { - - LOGGER.error("La source n'a pas été chargée"); - return false; - - } else { - - LOGGER.debug("La source est bien disponible"); - - let source = sourceManager.getSourceById(this._configuration.sources[i]); - - - - // on recupere l'id de l'unique source smartrouting - if (source.type === 'smartrouting') { - - this._linkedSource['smartrouting'] = source.configuration.id; - - } else if (source.type === 'pgr') { - - for (let j = 0; j < source.configuration.costs.length; j++) { - - let linkedIdRoute = source.configuration.costs[j].profile + source.configuration.costs[j].optimization; - let linkedIdIso = source.configuration.costs[j].profile + source.configuration.costs[j].costType; - this._linkedSource[linkedIdRoute] = source.configuration.id; - this._linkedSource[linkedIdIso] = source.configuration.id; - - } - - } else { - - // TODO : faire cette vérification aussi pendant le check de la ressource - LOGGER.error("La source n'est pas de type 'pgr' ou 'smartrouting'"); - return false; - - } - - } - - } - - return true; - - } - - /** - * - * @function - * @name getSourceIdFromRequest - * @description Récupérer l'id de la source concernée par la requête. - * Ce traitement est placé ici car c'est la ressource qui sait quelle source est concernée par la requête. - * @param {Request} request - Objet Request ou ou dérivant de la classe Request - * @return {string} Id de la source concernée par la requête - * - */ - getSourceIdFromRequest (request) { - - let source = ""; - - if (request.operation === "isochrone") { - - let useSmartrouting = false; - - if (request.costType === 'distance') { - // Note costValue est déjà en metres - useSmartrouting = request.costValue > this._distThreshold; - } else if (request.costType === 'time') { - // Note costValue est déjà en secondes - if (request.profile === 'car') { - useSmartrouting = request.costValue > this._timeThresholdCar - } else if (request.profile === 'pedestrian') { - useSmartrouting = request.costValue > this._timeThresholdPedestrian - } - } - - if (useSmartrouting) { - source = 'smartrouting'; - } else { - source = request.profile + request.costType; - } - - } else if (request.operation === "route") { - - // On décide de faire uniquement du PGR sur cette ressource dans le cas de l'iti - source = request.profile + request.optimization; - - } else { - return null; - } - - if (this._linkedSource[source]) { - return this._linkedSource[source]; - } else { - return null; - } - - } - - /** - * - * @function - * @name checkSourceAvailibilityFromRequest - * @description Savoir s'il y a une source disponible pour répondre à la requête. Par exemple, pour un itinéraire, il s'agira de savoir si un couple profile/optimization est disponible. - * Ce traitement est placé ici car c'est la ressource qui sait quelle source est concernée par la requête. - * @param {Request} request - Objet Request ou ou dérivant de la classe Request - * @return {boolean} - * - */ - checkSourceAvailibilityFromRequest (request) { - - let source = ""; - - if (request.operation === "isochrone") { - - let useSmartrouting = false; - - if (request.costType === 'distance') { - // Note costValue est déjà en metres - useSmartrouting = request.costValue > this._distThreshold; - } else if (request.costType === 'time') { - // Note costValue est déjà en secondes - if (request.profile === 'car') { - useSmartrouting = request.costValue > this._timeThresholdCar - } else if (request.profile === 'pedestrian') { - useSmartrouting = request.costValue > this._timeThresholdPedestrian - } - } - - if (useSmartrouting) { - source = 'smartrouting'; - } else { - source = request.profile + request.costType; - } - - } else if (request.operation === "route") { - - // On décide de faire uniquement du PGR sur cette ressource dans le cas de l'iti - source = request.profile + request.optimization; - - } else { - return false; - } - - if (this._linkedSource[source]) { - return true; - } else { - return false; - } - - } - -} diff --git a/src/js/sources/osrmSource.js b/src/js/sources/osrmSource.js index b5a507c1..3404bda0 100644 --- a/src/js/sources/osrmSource.js +++ b/src/js/sources/osrmSource.js @@ -116,7 +116,7 @@ module.exports = class osrmSource extends Source { // Chargement du fichier OSRM if (OSRM) { - this._osrm = new OSRM(osrmFile); + this._osrm = new OSRM({path: osrmFile, algorithm: "CH"}); super.connected = true; } else { throw errorManager.createError("OSRM is not available"); @@ -311,7 +311,7 @@ module.exports = class osrmSource extends Source { LOGGER.error("osrm error for nearest :"); LOGGER.error(err); reject("Internal OSRM error"); - + } else { LOGGER.debug("osrm response for nearest :"); @@ -569,7 +569,7 @@ module.exports = class osrmSource extends Source { } nativeSteps[k].intersections = nativeIntersections; - // Add maneuver extra + // Add maneuver extra let nativeManeuver = {}; // Test with hasOwnProperty because it can be 0 inside this property if (currentOsrmRouteStep.maneuver.hasOwnProperty("bearing_before")) { @@ -585,7 +585,7 @@ module.exports = class osrmSource extends Source { } nativeManeuver.location = [location.x, location.y]; } - + nativeSteps[k].maneuver = nativeManeuver; } @@ -616,7 +616,7 @@ module.exports = class osrmSource extends Source { * Ce traitement est placé ici car c'est à la source de renvoyer une réponse adaptée au proxy. * C'est cette fonction qui doit vérifier le contenu de la réponse. Une fois la réponse envoyée * au proxy, on considère qu'elle est correcte. - * @param {nearestRequest} nearestRequest - Objet nearestRequest + * @param {nearestRequest} nearestRequest - Objet nearestRequest * @param {osrmResponse} osrmResponse - Objet osrmResponse, réponse renvoyée par osrm * */ @@ -633,13 +633,13 @@ module.exports = class osrmSource extends Source { // Création de la réponse let nearestResponse = new NearestResponse(nearestRequest.resource, nearestRequest.coordinates); - // Récupération de l'ensemble des points de la réponse d'OSRM + // Récupération de l'ensemble des points de la réponse d'OSRM if (osrmResponse.waypoints) { LOGGER.debug(osrmResponse); if (osrmResponse.waypoints.length < 1) { throw errorManager.createError(" OSRM response is invalid: the number of waypoints is lower than 1. "); } else { - + for (let i=0; i < osrmResponse.waypoints.length; i++) { if (osrmResponse.waypoints[i].location) { @@ -668,7 +668,7 @@ module.exports = class osrmSource extends Source { } else { throw errorManager.createError(" OSRM response is invalid: no waypoints. "); } - + return nearestResponse; } diff --git a/src/js/sources/smartroutingSource.js b/src/js/sources/smartroutingSource.js deleted file mode 100644 index b0bd1726..00000000 --- a/src/js/sources/smartroutingSource.js +++ /dev/null @@ -1,473 +0,0 @@ -'use strict'; - -const Source = require('./source'); -const RouteResponse = require('../responses/routeResponse'); -const IsochroneResponse = require('../responses/isochroneResponse'); -const Route = require('../responses/route'); -const Portion = require('../responses/portion'); -const Line = require('../geometry/line'); -const Point = require('../geometry/point'); -const Polygon = require('../geometry/polygon'); -const Step = require('../responses/step'); -const Distance = require('../geography/distance'); -const Duration = require('../time/duration'); -const errorManager = require('../utils/errorManager'); -const log4js = require('log4js'); -const wkt = require('../geometry/formats/wkt'); -const httpQuery = require('../utils/httpQuery'); - - -// Création du LOGGER -var LOGGER = log4js.getLogger("SMARTROUTINGSOURCE"); - - -/** -* -* @class -* @name osrmSource -* @description Classe modélisant une source OSRM. -* -*/ - -module.exports = class smartroutingSource extends Source { - - /** - * - * @function - * @name constructor - * @description Constructeur de la classe osrmSource - * @param {json} sourceJsonObject - Description de la source en json - * - */ - constructor(sourceJsonObject) { - - // Constructeur parent - super(sourceJsonObject.id, "smartrouting", sourceJsonObject.description, sourceJsonObject.projection, sourceJsonObject.bbox); - - // Stockage de la configuration - this._configuration = sourceJsonObject; - - // Opérateur pour les requêtes http - this._httpQuery = new httpQuery({prefixUrl: this._configuration.storage.url}); - - } - - /** - * - * @function - * @name get configuration - * @description Récupérer la configuration de la source - * - */ - get configuration () { - return this._configuration; - } - - /** - * - * @function - * @name set configuration - * @description Attribuer la configuration de la source - * @param {json} conf - Description de la source en json - * - */ - set configuration (conf) { - this._configuration = conf; - } - - /** - * - * @function - * @name connect - * - */ - async connect() { - this._connected = true; - } - - /** - * - * @function - * @name disconnect - * - */ - async disconnect() { - this._connected = false; - } - - /** - * - * @function - * @name computeRequest - * @description Traiter une requête. - * @param {Request} request - Objet Request ou dérivant de la classe Request - * @return {Promise} - * - */ - computeRequest (request) { - LOGGER.debug("computeRequest()"); - - let query = ""; - let smartroutingRequest = {}; - - if (request.operation === "route") { - LOGGER.debug("operation request is route"); - - // Construction de l'objet pour la requête smart routing - if (request.type === "routeRequest") { - LOGGER.debug("type of request is routeRequest"); - - // Coordonnées - // start - smartroutingRequest.origin = request.start.x + "," + request.start.y; - // intermediates - if (request.intermediates.length !== 0) { - let waypoints = []; - for (let i = 0; i < request.intermediates.length; i++) { - waypoints.push(request.intermediates[i].x + "," + request.intermediates[i].y); - } - smartroutingRequest.waypoints = waypoints.join(";"); - } - // end - smartroutingRequest.destination = request.end.x + "," + request.end.y; - - // optimization - const mapMethods = { - shortest: "distance", - fastest: "time" - }; - smartroutingRequest.method = mapMethods[request.optimization]; - - // profil - const mapProfiles = { - car: "Voiture", - pedestrian: "Pieton" - }; - smartroutingRequest.graphName = mapProfiles[request.profile]; - - // constraints - const mapConstraintValues = { - tunnel: "Tunnel", - autoroute: "Toll", - pont: "Bridge" - }; - if (request.constraints && Array.isArray(request.constraints) && request.constraints.length > 0) { - let constraints = []; - - for (let i = 0; i < request.constraints.length; i++) { - if (request.constraints[i].type === 'avoid' || request.constraints[i].type === 'prefer') { - LOGGER.debug("constraint type " + request.constraints[i].type + " not allowed for this source"); - } else if (request.constraints[i].type === "banned") { - if (mapConstraintValues[request.constraints[i].value]) { - constraints.push(mapConstraintValues[request.constraints[i].value]); - } else { - LOGGER.debug("constraint value " + request.constraints[i].value + " not allowed for this source"); - } - } else { - LOGGER.debug("constraint type is unknown"); - } - } - - smartroutingRequest.exclusions = constraints.join(";"); - } else { - // il n'y rien à faire car pas de contraintes - LOGGER.debug("no contraints"); - } - - // projection - // projection demandée dans la requête - smartroutingRequest.srs = request.start.projection; - - // query - query = "itineraire/rest/route.json?"+Object.keys(smartroutingRequest).map(function (key) { return key + '=' + smartroutingRequest[key]}).join('&'); - - } else { - // TODO: qu'est-ce qui se passe si on arrive là, doit-on retourner une erreur ou une promesse - LOGGER.error("type of request not found"); - } - - } else if (request.operation === "isochrone") { - LOGGER.debug("operation request is isochrone"); - - // Construction de l'objet pour la requête smart routing - if (request.type === "isochroneRequest") { - LOGGER.debug("type of request is isochroneRequest"); - - // Coordonnées - // location - smartroutingRequest.location = request.point.x + "," + request.point.y; - - // optimization - const mapMethods = { - distance: "distance", - time: "time" - }; - smartroutingRequest.method = mapMethods[request.costType]; - - // profil - const mapProfiles = { - car: "Voiture", - pedestrian: "Pieton" - }; - smartroutingRequest.graphName = mapProfiles[request.profile]; - - // valeur du cout - if ( smartroutingRequest.method === 'time') { - // Note costValue est déjà en secondes - smartroutingRequest.time = request.costValue; - } else if ( smartroutingRequest.method === 'distance' ) { - // Note costValue est déjà en metres - smartroutingRequest.distance = request.costValue; - } - - // sens de parcours - smartroutingRequest.reverse = request.direction === 'arrival' ? true : false; - - // autres options - smartroutingRequest.smoothing = false; - smartroutingRequest.holes = false; - - // constraints - const mapConstraintValues = { - tunnel: "Tunnel", - autoroute: "Toll", - pont: "Bridge" - }; - if (request.constraints && Array.isArray(request.constraints) && request.constraints.length > 0) { - let constraints = []; - - for (let i = 0; i < request.constraints.length; i++) { - if (request.constraints[i].type === 'avoid' || request.constraints[i].type === 'prefer') { - LOGGER.debug("constraint type " + request.constraints[i].type + " not allowed for this source"); - } else if (request.constraints[i].type === "banned") { - if (mapConstraintValues[request.constraints[i].value]) { - constraints.push(mapConstraintValues[request.constraints[i].value]); - } else { - LOGGER.debug("constraint value " + request.constraints[i].value + " not allowed for this source"); - } - } else { - LOGGER.debug("constraint type is unknown"); - } - } - - smartroutingRequest.exclusions = constraints.join(";"); - } else { - // il n'y rien à faire car pas de contraintes - LOGGER.debug("no contraints"); - } - - // projection - smartroutingRequest.srs = request.askedProjection; - - // query - query = "isochrone/isochrone.json?"+Object.keys(smartroutingRequest).map(function (key) { return key + '=' + smartroutingRequest[key]}).join('&'); - - } else { - // TODO: qu'est-ce qui se passe si on arrive là, doit-on retourner une erreur ou une promesse ? - LOGGER.error("type of request not found"); - } - - } else { - // TODO: qu'est-ce qui se passe si on arrive là, doit-on retourner une erreur ou une promesse ? - LOGGER.error("request operation not found"); - } - - LOGGER.debug("smartroutingRequest:"); - LOGGER.debug(smartroutingRequest); - - var self = this; - LOGGER.debug("smartrouting query:"); - LOGGER.debug(query); - return this._httpQuery.get(query).then( (response) => { - const result = JSON.parse(response.body); - if( request.operation === "route" ) { - return self.writeRouteResponse(request, result); - } - if ( request.operation === "isochrone" ) { - return self.writeIsochroneResponse(request, result); - } - }).catch( (error) => { - LOGGER.debug(error); - return Promise.reject(errorManager.createError("SmartRouting http query fail" , 503)); - }); - } - - /** - * - * @function - * @name writeRouteResponse - * @description Pour traiter la réponse du moteur et la ré-écrire pour le proxy. - * @param {Request} routeRequest - Objet Request ou dérivant de la classe Request - * @param {smartroutingResponse} smartroutingResponse - Objet smartroutingResponse - * - */ - writeRouteResponse (routeRequest, smartroutingResponse) { - - LOGGER.debug("writeRouteResponse()"); - LOGGER.debug(smartroutingResponse); - - let resource; - let start; - let end; - let profile; - let optimization; - let route; - - // Récupération des paramètres de la requête que l'on veut transmettre dans la réponse - // --- - // resource - resource = routeRequest.resource; - - // profile - profile = routeRequest.profile; - - // optimization - optimization = routeRequest.optimization; - - // projection - let askedProjection = routeRequest.start.projection; - // pas de reprojections à faire: contrairement à ce qui est dit dans la doc, les géometries retournées par le service sont dans le système demandé - // --- - - // convertion de la geometry - const wayGeojson = wkt.toGeoJSON(smartroutingResponse.geometryWkt); - let way = new Line(wayGeojson, 'geojson', askedProjection); - - // start et end - start = new Point(wayGeojson.coordinates[0][0], wayGeojson.coordinates[0][1], askedProjection); - end = new Point(wayGeojson.coordinates[wayGeojson.coordinates.length-1][0], wayGeojson.coordinates[wayGeojson.coordinates.length-1][1], askedProjection); - - // construction objet reponse - let routeResponse = new RouteResponse(resource, start, end, profile, optimization); - - // routes - // Il ne peut y avoir qu'un seul itinéraire - let portions = new Array(); - - // On commence par créer l'itinéraire avec les attributs obligatoires - route = new Route( way ); - - // On récupère la distance et la durée - route.distance = new Distance(smartroutingResponse.distance,"meter"); - route.duration = new Duration(smartroutingResponse.duration,"second"); - - // On va gérer les portions qui sont des parties de l'itinéraire entre deux points intermédiaires - let routeDistance = 0; - let routeDuration = 0; - for (let j = 0; j < smartroutingResponse.legs.length; j++) { - LOGGER.debug("Portion (SMART ROUTING legs) number " + j); - - let currentRouteLeg = smartroutingResponse.legs[j]; - - const firstPoint = currentRouteLeg.steps[0].points[0]; - - if (currentRouteLeg.steps[0].points.length > 0) { - let legStart = new Point(firstPoint[0], firstPoint[1], askedProjection); - - const lastPoint = currentRouteLeg.steps[currentRouteLeg.steps.length-1].points[currentRouteLeg.steps[currentRouteLeg.steps.length-1].points.length-1]; - let legEnd = new Point( lastPoint[0], lastPoint[1], askedProjection); - - portions[j] = new Portion(legStart, legEnd); - - // On récupère la distance et la durée - // Note : distanceMeters et durationSeconds ne sont pas dans la doc - portions[j].distance = new Distance(currentRouteLeg.distanceMeters, "meter"); - portions[j].duration = new Duration(currentRouteLeg.durationSeconds, "second"); - - // Steps - let steps = new Array(); - - // On va associer les étapes à la portion concernée - for (let k=0; k < currentRouteLeg.steps.length; k++) { - LOGGER.debug("Step number " + k + " of portion number " + j); - - let currentRouteStep = currentRouteLeg.steps[k]; - const stepGeometry = { - type: "linestring", - coordinates: currentRouteStep.points - } - steps[k] = new Step( new Line(stepGeometry, "geojson", askedProjection) ); - - // Ajout de l'attribut name - steps[k].setAttributById("name", currentRouteStep.name); - - // instruction de navigation - steps[k].instruction = currentRouteStep.navInstruction; - - // On récupère la distance et la durée - steps[k].distance = new Distance(Math.round(currentRouteStep.distanceMeters * 10) / 10, "meter"); - steps[k].duration = new Duration(Math.round(currentRouteStep.durationSeconds * 10) / 10, "second"); - } - portions[j].steps = steps; - } - // On récupère la distance et la durée - routeDistance += parseFloat(currentRouteLeg.distanceMeters); - routeDuration += parseFloat(currentRouteLeg.durationSeconds); - } - - // On récupère la distance et la durée - route.distance = new Distance(Math.round(routeDistance * 10) / 10, "meter"); - route.duration = new Duration(Math.round(routeDuration * 10) / 10, "second"); - - route.portions = portions; - routeResponse.routes = [route]; - - return routeResponse; - } - - /** - * - * @function - * @name writeIsochroneResponse - * @description Pour traiter la réponse du moteur et la ré-écrire pour le proxy. - * @param {Request} request - Objet Request ou dérivant de la classe Request - * @param {smartroutingResponse} smartroutingResponse - Objet smartroutingResponse - * - */ - writeIsochroneResponse(isochroneRequest, smartroutingResponse) { - - LOGGER.debug("writeIsochroneResponse()"); - - LOGGER.debug("smartroutingResponse :"); - LOGGER.debug(smartroutingResponse); - - let location = {}; - let geometry = {}; - - // projection - const projection = smartroutingResponse.srs; - // pas de reprojection à faire. Le service répond dans le système demandé. - - // Location - const locationCoords = JSON.parse("[" + smartroutingResponse.location + "]"); - location = new Point(locationCoords[0], locationCoords[1], projection); - - // Geometrie - let rawGeometry = wkt.toGeoJSON(smartroutingResponse.wktGeometry); - - // Cas où il n'y a pas d'isochrone car costValue trop faible - if (rawGeometry === null) { - rawGeometry = { - type: 'Point', - coordinates: locationCoords - }; - } - - // Création d'un objet Polygon à partir du GeoJSON reçu. - geometry = new Polygon(rawGeometry, "geojson", projection); - - /* Envoi de la réponse au proxy. */ - return new IsochroneResponse( - location, - isochroneRequest.resource, - isochroneRequest.costType, - isochroneRequest.costValue, - geometry, - isochroneRequest.profile, - isochroneRequest.direction, - projection, - isochroneRequest.timeUnit, - isochroneRequest.distanceUnit - ); - } -} diff --git a/src/js/sources/sourceManager.js b/src/js/sources/sourceManager.js index fa8b1927..3c8ad0ee 100644 --- a/src/js/sources/sourceManager.js +++ b/src/js/sources/sourceManager.js @@ -5,7 +5,6 @@ const path = require('path'); const assert = require('assert').strict; const osrmSource = require('../sources/osrmSource'); const pgrSource = require('../sources/pgrSource'); -const smartroutingSource = require('../sources/smartroutingSource'); const valhallaSource = require('../sources/valhallaSource'); const log4js = require('log4js'); @@ -38,19 +37,18 @@ module.exports = class sourceManager { // Descriptions des sources vérifiées par le manager this._checkedSourceConfiguration = {}; - // Manager des projections + // Manager des projections this._projectionManager = projectionManager; // Manager de bases de données (utiles pour certaines sources) this._baseManager = baseManager; - // Correspondance entre les sources et les opérations possibles + // Correspondance entre les sources et les opérations possibles // Le contenu de ce tableau dépend du moteur et du code écrit dans la source correspondante // Par exemple, le projet OSRM permet de faire du nearest et nous avons choisis de l'implémenter dans Road2 this._operationsByType = { "osrm": ["nearest", "route"], "pgr": ["route", "isochrone"], - "smartrouting": ["route", "isochrone"], "valhalla": ["route", "isochrone"] }; @@ -84,7 +82,7 @@ module.exports = class sourceManager { * @name isCheckedSourceAvailable * @description Fonction utilisée pour vérifier si une source a été vérifiée * @param {string} id - Id de la source - * @return {boolean} + * @return {boolean} * */ @@ -129,7 +127,7 @@ module.exports = class sourceManager { * @name isLoadedSourceAvailable * @description Fonction utilisée pour vérifier si une source a été chargée * @param {string} id - Id de la source - * @return {boolean} + * @return {boolean} * */ @@ -154,7 +152,7 @@ module.exports = class sourceManager { * @name checkSourceDirectory * @description Fonction utilisée pour vérifier un dossier contenant des sources. * @param {string} directory - Dossier qui contient les configurations des ressources - * @return {boolean} + * @return {boolean} * */ @@ -182,6 +180,10 @@ module.exports = class sourceManager { for (let i = 0; i < fileList.length; i++) { let source = fileList[i]; + if (!source.endsWith(".source")) { + LOGGER.warn("Le fichier " + source + " n'est pas un fichier de source (extension .source) et ne sera pas vérifié."); + continue; + } let sourceFile = ""; try { sourceFile = directory + "/" + source; @@ -192,7 +194,7 @@ module.exports = class sourceManager { let sourceConf = {}; try { - // Il s'agit juste de savoir si le fichier est lisible par Road2, il sera exploité plus tard + // Il s'agit juste de savoir si le fichier est lisible par Road2, il sera exploité plus tard sourceConf = JSON.parse(fs.readFileSync(sourceFile)); } catch (error) { LOGGER.error("Mauvaise configuration: impossible de lire ou de parser le fichier de source: " + sourceFile); @@ -225,7 +227,7 @@ module.exports = class sourceManager { * @name checkSourceConfiguration * @description Fonction utilisée pour vérifier la configuration d'une source. * @param {json} sourceJsonObject - Description JSON de la source - * @return {boolean} + * @return {boolean} * */ @@ -299,7 +301,7 @@ module.exports = class sourceManager { } } - // Projection + // Projection if (!sourceJsonObject.projection) { LOGGER.error("Mauvaise configuration: source.projection absent"); return false; @@ -311,7 +313,7 @@ module.exports = class sourceManager { } } - // Bbox + // Bbox if (!sourceJsonObject.bbox) { LOGGER.error("Mauvaise configuration: source.bbox absent"); return false; @@ -348,8 +350,6 @@ module.exports = class sourceManager { validation = await this.checkSourcePgr(sourceJsonObject); } else if (sourceJsonObject.type === "valhalla") { validation = this.checkSourceValhalla(sourceJsonObject); - } else if (sourceJsonObject.type === "smartrouting") { - validation = this.checkSourceSmartrouting(sourceJsonObject); } else { LOGGER.error("La source indique un type invalide : " + sourceJsonObject.type); return false; @@ -375,7 +375,7 @@ module.exports = class sourceManager { * @name checkSourceOsrm * @description Fonction utilisée pour vérifier le contenu d'un fichier de description d'une source osrm. * @param {json} sourceJsonObject - Description JSON de la source - * @return {boolean} + * @return {boolean} * */ @@ -383,7 +383,7 @@ module.exports = class sourceManager { LOGGER.info("Verification de la source osrm..."); - // On vérifie que le module osrm est disponible + // On vérifie que le module osrm est disponible try { let osrmTest = require('osrm'); } catch(error) { @@ -446,7 +446,7 @@ module.exports = class sourceManager { * @name checkSourcePgr * @description Fonction utilisée pour vérifier le contenu d'un fichier de description d'une source pgr. * @param {json} sourceJsonObject - Description JSON de la source - * @return {boolean} + * @return {boolean} * */ @@ -469,7 +469,7 @@ module.exports = class sourceManager { return false; } else { - + LOGGER.debug("'source.storage' présent"); if (!sourceJsonObject.storage.base) { @@ -486,7 +486,7 @@ module.exports = class sourceManager { return false; } else { LOGGER.debug("'source.storage.base.dbConfig' présent"); - + if (!(await this._baseManager.checkBaseConfiguration(sourceJsonObject.storage.base.dbConfig))) { LOGGER.error("Mauvaise configuration : 'source.storage.base.dbConfig' invalide"); return false; @@ -537,12 +537,12 @@ module.exports = class sourceManager { if (!sourceJsonObject.storage.base.attributes[j].key) { LOGGER.error("Mauvaise configuration : 'source.storage.base.attributes["+j+"].key' est absent"); return false; - } + } if (!sourceJsonObject.storage.base.attributes[j].column) { LOGGER.error("Mauvaise configuration : 'source.storage.base.attributes["+j+"].column' est absent"); return false; - } + } if (!sourceJsonObject.storage.base.attributes[j].default) { LOGGER.error("Mauvaise configuration : 'source.storage.base.attributes["+j+"].default' est absent"); @@ -631,41 +631,6 @@ module.exports = class sourceManager { } - /** - * - * @function - * @name checkSourceSmartrouting - * @description Fonction utilisée pour vérifier le contenu d'un fichier de description d'une source smartrouting. - * @param {json} sourceJsonObject - Description JSON de la source - * @return {boolean} - * - */ - - checkSourceSmartrouting(sourceJsonObject) { - - LOGGER.info("Verification de la source smartrouting..."); - - // Storage - if (!sourceJsonObject.storage) { - LOGGER.error("Mauvaise configuration : 'source.storage' absent"); - return false; - } else { - - LOGGER.debug("'source.storage' présent"); - - if (!sourceJsonObject.storage.url) { - LOGGER.error("Mauvaise configuration : 'source.storage.url' absent"); - return false; - } else { - LOGGER.debug("'source.storage.url' présent"); - // TODO: vérifier la forme de l'URL avec une regex - } - } - - LOGGER.info("Fin de la verification de la source smartrouting."); - return true; - - } /** * @@ -673,13 +638,13 @@ module.exports = class sourceManager { * @name checkSourceValhalla * @description Fonction utilisée pour vérifier le contenu d'un fichier de description d'une source valhalla. * @param {json} sourceJsonObject - Description JSON de la source - * @return {boolean} + * @return {boolean} * */ checkSourceValhalla(sourceJsonObject) { - LOGGER.info("Verification de la source smartrouting..."); + LOGGER.info("Verification de la source valhalla..."); // Storage if (!sourceJsonObject.storage) { @@ -770,7 +735,7 @@ module.exports = class sourceManager { } - LOGGER.info("Fin de la verification de la source smartrouting."); + LOGGER.info("Fin de la verification de la source valhalla."); return true; } @@ -781,7 +746,7 @@ module.exports = class sourceManager { * @name checkDuplicationLoadedSource * @description Fonction utilisée pour vérifier que le contenu d'un fichier de description d'une source est bien le même qu'un autre. * @param {json} sourceJsonObject - Description JSON de la source - * @return {boolean} + * @return {boolean} * */ @@ -812,7 +777,7 @@ module.exports = class sourceManager { * @name checkDuplicationCheckedSource * @description Fonction utilisée pour vérifier que le contenu d'un fichier de description d'une source est bien le même qu'un autre. * @param {json} sourceJsonObject - Description JSON de la source - * @return {boolean} + * @return {boolean} * */ @@ -856,14 +821,14 @@ module.exports = class sourceManager { * * @function * @name flushCheckedSource - * @description Vider la liste des source déjà vérifiées + * @description Vider la liste des source déjà vérifiées * */ flushCheckedSource() { this._checkedSourceId = new Array(); this._checkedSourceConfiguration = {}; - + } /** @@ -947,8 +912,6 @@ module.exports = class sourceManager { // Création de la source source = new pgrSource(sourceJsonObject, base); - } else if (sourceJsonObject.type === "smartrouting") { - source = new smartroutingSource(sourceJsonObject); } else if (sourceJsonObject.type === "valhalla") { source = new valhallaSource(sourceJsonObject); } else { @@ -970,8 +933,8 @@ module.exports = class sourceManager { * * @function * @name connectSource - * @description Fonction utilisée pour connecter une source. - * On la sépare volontairement du load de la source car on veut pouvoir gérer ces actions de manière indépendante. + * @description Fonction utilisée pour connecter une source. + * On la sépare volontairement du load de la source car on veut pouvoir gérer ces actions de manière indépendante. * @param {string} sourceId - Id de la source que l'on veut connecter * */ @@ -998,7 +961,7 @@ module.exports = class sourceManager { * * @function * @name disconnectSource - * @description Fonction utilisée pour déconnecter une source. + * @description Fonction utilisée pour déconnecter une source. * @param {string} sourceId - Id de la source que l'on veut déconnecter * */ @@ -1048,23 +1011,23 @@ module.exports = class sourceManager { let nbSourceConnected = 0; for (let i = 0; i < this._loadedSourceId.length; i++) { - + LOGGER.info("Source : " + this._loadedSourceId[i]); if (!(await this.connectSource(this._loadedSourceId[i]))) { LOGGER.error("Source " + this._loadedSourceId[i] + " non connectée"); - // TODO : on continue de connecter les autres sources et on gère après coup la MAJ des ressources, du getcap, etc... - // Pour le moment, s'il y a une source qui ne fonctionne pas, on arrête le serveur + // TODO : on continue de connecter les autres sources et on gère après coup la MAJ des ressources, du getcap, etc... + // Pour le moment, s'il y a une source qui ne fonctionne pas, on arrête le serveur return false; } else { LOGGER.info("Source " + this._loadedSourceId[i] + " connectée"); nbSourceConnected++; - + } - + } LOGGER.info("Les démarrages se sont bien déroulés."); @@ -1106,7 +1069,7 @@ module.exports = class sourceManager { let nbSourceDisconnected = 0; for (let i = 0; i < this._loadedSourceId.length; i++) { - + LOGGER.info("Source : " + this._loadedSourceId[i]); if (!(await this.disconnectSource(this._loadedSourceId[i]))) { @@ -1118,9 +1081,9 @@ module.exports = class sourceManager { LOGGER.info("Source " + this._loadedSourceId[i] + " déconnectée"); nbSourceDisconnected++; - + } - + } LOGGER.info("Les déconnexions se sont bien déroulés."); diff --git a/src/js/sources/valhallaSource.js b/src/js/sources/valhallaSource.js index 43c21cd4..36a269f0 100644 --- a/src/js/sources/valhallaSource.js +++ b/src/js/sources/valhallaSource.js @@ -12,16 +12,12 @@ const Step = require('../responses/step'); const Distance = require('../geography/distance'); const Duration = require('../time/duration'); const errorManager = require('../utils/errorManager'); -const { exec } = require('child_process'); const turf = require('@turf/turf'); +const { Actor } = require("@valhallajs/valhallajs") // Création du LOGGER const log4js = require('log4js'); const LOGGER = log4js.getLogger("VALHALLASOURCE"); -// Récupération de la valeur du maxBuffer en variable d'environment variable ou valorisation par défaut (1MB) -const maxBuffer = process.env.EXEC_MAX_BUFFER_SIZE ? parseInt(process.env.EXEC_MAX_BUFFER_SIZE, 10) : 1024 * 1024; -// Récupération de la valeur du timeout pour l'execution du valhalla_service en variable d'environnement ou valorisation par défaut (0) -const execTimeout = process.env.EXEC_TIMEOUT ? parseInt(process.env.EXEC_TIMEOUT, 10) : 0; /** * @@ -195,39 +191,32 @@ module.exports = class valhallaSource extends Source { costingOptionsString += "}}"; // Permet de grandement se simplifier le parsing !! const optionsString = `"directions_options":{"format":"osrm"}`; - const commandString = `valhalla_service ${this._configuration.storage.config} route '{${locationsString},${costingString},${costingOptionsString},${optionsString}}' `; - const options = { maxBuffer: maxBuffer, timeout: execTimeout }; + const commandString = `{${locationsString},${costingString},${costingOptionsString},${optionsString}}`; LOGGER.info(commandString); return new Promise( (resolve, reject) => { try { - exec(commandString, options, (err, stdout, stderr) => { - - // Du moment qu'OSRM a répondu, on considère que la source est joignable - this.state = "green"; - - if (err) { - // mais on ne renvoie pas l'erreur à l'utilisateur - reject(errorManager.createError(" No path found ", 404)); - LOGGER.error("valhalla error for route :"); - LOGGER.error(err); - - } else { + Actor.fromConfigFile(this._configuration.storage.config).then((valhallaActor) => { + valhallaActor.route(commandString).then((valhallaResponse) => { + // Du moment que Valhalla a répondu, on considère que la source est joignable + this.state = "green"; LOGGER.debug("valhalla response for route :"); - LOGGER.debug(stdout); + LOGGER.debug(valhallaResponse); try { - resolve(this.writeRouteResponse(request, stdout)); + resolve(this.writeRouteResponse(request, valhallaResponse)); } catch (error) { reject(error); } - - } - + }).catch((err) => { + // mais on ne renvoie pas l'erreur à l'utilisateur + reject(errorManager.createError(" No path found ", 404)); + LOGGER.error("valhalla error for route :"); + LOGGER.error(err); + }); }); - } catch (error) { // Pour une raison que l'on ignore, la source n'est plus joignable this.state = "red"; @@ -303,39 +292,32 @@ module.exports = class valhallaSource extends Source { const contoursString = `"contours":[{"${request.costType}":${costValue}}]`; const reverseString = `"reverse":${reverse}`; const polygonsString = `"polygons":true`; - const commandString = `valhalla_service ${this._configuration.storage.config} isochrone '{${locationsString},${costingString},${costingOptionsString},${contoursString},${reverseString},${polygonsString}}' `; - const options = { maxBuffer: maxBuffer, timeout: execTimeout }; + const commandString = `{${locationsString},${costingString},${costingOptionsString},${contoursString},${reverseString},${polygonsString}}`; LOGGER.info(commandString); return new Promise( (resolve, reject) => { try { - exec(commandString, options, (err, stdout, stderr) => { - - // Du moment qu'OSRM a répondu, on considère que la source est joignable - this.state = "green"; - - if (err) { - // mais on ne renvoie pas l'erreur à l'utilisateur - LOGGER.error("valhalla error for route :"); - LOGGER.error(err); - reject(errorManager.createError(" No path found ", 404)); - - } else { - - LOGGER.debug("valhalla response for iso :"); - LOGGER.debug(stdout); - - try { - resolve(this.writeIsochroneResponse(request, stdout)); - } catch (error) { - reject(error); - } - - } - - }); - + Actor.fromConfigFile(this._configuration.storage.config).then((valhallaActor) => { + valhallaActor.isochrone(commandString).then((valhallaResponse) => { + // Du moment que Valhalla a répondu, on considère que la source est joignable + this.state = "green"; + + LOGGER.debug("valhalla response for iso :"); + LOGGER.debug(valhallaResponse); + + try { + resolve(this.writeIsochroneResponse(request, valhallaResponse)); + } catch (error) { + reject(error); + } + }).catch((err) => { + // mais on ne renvoie pas l'erreur à l'utilisateur + reject(errorManager.createError(" No path found ", 404)); + LOGGER.error("valhalla error for route :"); + LOGGER.error(err); + }); + }); } catch (error) { // Pour une raison que l'on ignore, la source n'est plus joignable this.state = "red"; diff --git a/test/functional/request/cucumber/features/req-simple-1.0.0-smartrouting.feature b/test/functional/request/cucumber/features/req-simple-1.0.0-smartrouting.feature deleted file mode 100644 index 5feac4aa..00000000 --- a/test/functional/request/cucumber/features/req-simple-1.0.0-smartrouting.feature +++ /dev/null @@ -1,100 +0,0 @@ -Feature: Road2-SMARTROUTING - Tests fonctionnels complémentaires de Road2 via SmartRouting - - Background: - Given I have loaded all my test configuration in "../../configurations/local-service.json" - - Scenario Outline: [] Isochrone sur l'API simple 1.0.0 sur une ressource smartpgr avec appel à la source smartrouting - Given an "" request on operation "isochrone" in api "simple" "1.0.0" - And with default parameters for "isochrone-smartpgr" - And with query parameters: - | key | value | - | costType | distance | - | costValue | 31000 | - When I send the request - Then the server should send a response with status 200 - And the response should have an header "content-type" with value "application/json" - And the response should contain a complete and valid iso - - Examples: - | method | - | GET | - | POST | - - Scenario Outline: [] Isochrone sur l'API simple 1.0.0 sur une ressource smartpgr avec appel à la source pgr - Given an "" request on operation "isochrone" in api "simple" "1.0.0" - And with default parameters for "isochrone-smartpgr" - And with query parameters: - | key | value | - | costType | distance | - | costValue | 1000 | - When I send the request - Then the server should send a response with status 200 - And the response should have an header "content-type" with value "application/json" - And the response should contain a complete and valid iso - - Examples: - | method | - | GET | - | POST | - - Scenario: [GET] Isochrone sur l'API simple 1.0.0 avec une contrainte sur une ressource smartpgr avec appel à la source smartrouting - Given an "GET" request on operation "isochrone" in api "simple" "1.0.0" - And with default parameters for "isochrone-smartpgr" - And with query parameters: - | key | value | - | costType | distance | - | costValue | 1000 | - | constraints | {"constraintType":"banned","key":"waytype","operator":"=","value":"autoroute"} | - When I send the request - Then the server should send a response with status 200 - And the response should have an header "content-type" with value "application/json" - And the response should contain a complete and valid iso - And the response should contain an attribute "constraints.[0].key" - - Scenario: [GET] Isochrone sur l'API simple 1.0.0 avec une contrainte sur une ressource smartpgr avec appel à la source smartrouting - Given an "GET" request on operation "isochrone" in api "simple" "1.0.0" - And with default parameters for "isochrone-smartpgr" - And with query parameters: - | key | value | - | costType | distance | - | costValue | 31000 | - | constraints | {"constraintType":"banned","key":"waytype","operator":"=","value":"autoroute"} | - When I send the request - Then the server should send a response with status 200 - And the response should have an header "content-type" with value "application/json" - And the response should contain a complete and valid iso - And the response should contain an attribute "constraints.[0].key" - - Scenario Outline: [] Isochrone sur l'API simple 1.0.0 avec un geometryFormat polyline à partir d'une géométrie générée par smartrouting - Given an "" request on operation "isochrone" in api "simple" "1.0.0" - And with default parameters for "isochrone-smartpgr" - And with query parameters: - | key | value | - | costType | distance | - | costValue | 31000 | - | geometryFormat | polyline | - When I send the request - Then the server should send a response with status 200 - And the response should have an header "content-type" with value "application/json" - - Examples: - | method | - | GET | - | POST | - - Scenario Outline: [] Isochrone sur l'API simple 1.0.0 avec geometryFormat=wkt - Given an "" request on operation "isochrone" in api "simple" "1.0.0" - And with default parameters for "isochrone-smartpgr" - And with query parameters: - | key | value | - | geometryFormat | wkt | - When I send the request - Then the server should send a response with status 200 - And the response should have an header "content-type" with value "application/json" - And the response should contain a complete and valid iso - And the response should contain a string attribute "geometry" - Examples: - | method | - | GET | - | POST | \ No newline at end of file diff --git a/test/integration/mocha/resources/integrationSmartPgrResource.js b/test/integration/mocha/resources/integrationSmartPgrResource.js deleted file mode 100644 index ab5b8aef..00000000 --- a/test/integration/mocha/resources/integrationSmartPgrResource.js +++ /dev/null @@ -1,113 +0,0 @@ -const assert = require('assert'); -const SmartpgrResource = require('../../../../src/js/resources/smartpgrResource'); -const IsochroneRequest = require('../../../../src/js/requests/isochroneRequest'); -const logManager = require('../logManager'); - -const sinon = require('sinon'); - -describe('Test de la classe SmartpgrResource', function() { - - before(function() { - // runs before all tests in this block - logManager.manageLogs(); - }); - - let resourceConfiguration = { - "resource": { - "id": "test-smartpgr", - "type": "smartpgr", - "threshold" : 30000, - "description": "Exemple d'une ressource SMARTPGR.", - "topology": { - "description": "Données pgr", - "storage": { - "dbConfig": "/home/docker/app/src/config/dbs/db_config_test.json" - }, - "projection": "EPSG:4326" - }, - "sources": [ - { - "id": "test-smartrouting", - "type": "smartrouting", - "storage": { - "url" : "https://wxs.ign.fr/calcul" - } - }, - { - "id": "test-car-fastest", - "type": "pgr", - "storage": { - "dbConfig": "/home/docker/app/src/config/dbs/db_config_test.json", - "costColumn": "cost_s_car", - "rcostColumn": "reverse_cost_s_car" - }, - "cost": { - "profile": "car", - "optimization": "fastest", - "compute": { - "storage": { - "file": "/home/docker/route-graph-generator/configuration/costs_calculation_sample.json" - } - } - } - } - ], - "availableOperations":[ - - ], - "defaultSourceId": "test-car-fastest", - "boundingBox": "-180,-90,180,90", - "defaultProjection": "EPSG:4326", - "availableProjections": ["EPSG:4326","EPSG:2154"] - } - }; - - let operations = {isochrone:{}}; - - let resource = new SmartpgrResource(resourceConfiguration, operations); - - describe('Test du constructeur et des getters', function() { - - it('Get Id', function() { - assert.equal(resource.id, "test-smartpgr"); - }); - - it('Get Type', function() { - assert.equal(resource.type, "smartpgr"); - }); - - it('Get Configuration', function() { - assert.deepEqual(resource.configuration, resourceConfiguration.resource); - }); - - it('Get LinkedSource', function() { - let reference = {}; - reference["cartime"] = "test-car-fastest"; - reference["smartrouting"] = "test-smartrouting"; - assert.deepEqual(resource.linkedSource, reference); - }); - - }); - - describe('Test du constructeur et des getters', function() { - - // Pour ne pas dépendre de la classe RouteRequest - let request = sinon.mock(IsochroneRequest); - request.operation = "isochrone" - request.profile = "car"; - request.costType = "time"; - request.timeUnit = "second"; - - it('getSourceIdFromRequest()_1', function() { - request.costValue = 830; - assert.equal(resource.getSourceIdFromRequest(request), "test-car-fastest"); - }); - - it('getSourceIdFromRequest()_2', function() { - request.costValue = 831; - assert.equal(resource.getSourceIdFromRequest(request), "test-smartrouting"); - }); - - }); - -}); diff --git a/test/integration/mocha/sources/integrationSmartroutingSource.js b/test/integration/mocha/sources/integrationSmartroutingSource.js deleted file mode 100644 index 52de53cc..00000000 --- a/test/integration/mocha/sources/integrationSmartroutingSource.js +++ /dev/null @@ -1,78 +0,0 @@ -const assert = require('assert'); -const smartroutingSource = require('../../../../src/js/sources/smartroutingSource'); -const RouteRequest = require('../../../../src/js/requests/routeRequest'); -const logManager = require('../logManager'); - -const sinon = require('sinon'); - -describe('Test de la classe smartroutingSource', function() { - - before(function() { - // runs before all tests in this block - logManager.manageLogs(); - }); - - let sourceDescription = { - "id": "test-smartrouting", - "type": "smartrouting", - "storage": { - "url" : "https://wxs.ign.fr/calcul" - } - }; - - let source = new smartroutingSource(sourceDescription); - - describe('Test du constructeur et des getters', function() { - - it('Get Source id', function() { - assert.equal(source.id, "test-smartrouting"); - }); - - it('Get Source type', function() { - assert.equal(source.type, "smartrouting"); - }); - - it('Get Source connected', function() { - assert.equal(source.connected, false); - }); - - it('Get Source configuration', function() { - assert.deepEqual(source.configuration, sourceDescription); - }); - - }); - - describe('Test de connect()', function() { - - it('Connect()', async function() { - await source.connect(); - }); - - }); - - describe('Test de disconnect()', function() { - - it('Disconnect()', async function() { - await source.disconnect(); - }); - - }); - - describe('Test de computeRequest() et writeRouteResponse()', function() { - this.timeout(10000); - - let resource = "resource-test"; - let start = {x: 8.732901, y: 41.928821}; - let end = {x: 8.76385, y: 41.953932}; - let profile = "car"; - let optimization = "fastest"; - let routeRequest = new RouteRequest(resource, start, end, profile, optimization); - - it('computeRequest() should return a routeResponse', async function() { - const routeResponse = await source.computeRequest(routeRequest); - assert.equal(routeResponse.resource, resource); - }); - - }); - -}); diff --git a/test/www/isochrone.html b/test/www/isochrone.html index abab19e0..94b2fd0c 100644 --- a/test/www/isochrone.html +++ b/test/www/isochrone.html @@ -38,8 +38,6 @@

Ressource :

- -