Recherche par Addresse #1

Closed
opened 2021-10-22 15:02:57 +02:00 by felix.baylac · 5 comments
Member

Pour le moment, nous ne supportons le test d'éligibilité que via un numéro de PTO. Ce qui est assez limité étant donné que dans pas mal de cas, on peut se retrouver avec un logement éligible à l'offre Axione mais n'ayant jamais été raccordé au réseau fibre, et donc ne possédant pas encore de PTO.

L'API interop-fibre nous propose d'utiliser 3 différents référentiels géographiques pour faire une recherche d'éligibilité:

  1. Hexaclé.
  2. BAN.
  3. RIVOLI (code issu du référentiel FANTOIR).

Hexaclé est un référentiel propriétaire appartenant à la poste, nous n'y avons pas accès.

Le référentiel BAN, bien que présent dans l'interface du webservice, n'est pas encore implémenté par Axione. Voir le thread e-mail https://listes.aquilenet.fr/arc/admin-ftth-axione/2021-09/msg00145.html pour plus d'infos.

Ça nous laisse avec pour seule option le codage RIVOLI. Si on regarde le WSDL de description du webservice, on voit qu'on aura besoin des champs suivants pour la requête:

<xs:complexType name='ReferenceRivoliType'>
    <xs:attribute  use='required' name='codeInsee' type='xs:string'/>
    <xs:attribute  use='required' name='codeRivoli' type='xs:string'/>
    <xs:attribute  use='required' name='numeroVoie' type='xs:nonNegativeInteger'/>
    <xs:attribute  use='optional' name='complementNumeroVoie' type='xs:string' />
</xs:complexType>

Toutes ces données sont issues du fichier FANTOIR. Ce fichier est librement disponible, mis a disposition par data.gouv.fr. En revanche, contrairement a BAN, il ne semble pas y avoir d'API en ligne nous permettant de facilement exploiter ces données. Nous allons devoir faire ça nous-même.

Le fichier FANTOIR est distribué sous la forme d'un fichier texte plat, il n'est pas directement exploitable tel quel.

Bonne nouvelle: l'Etalab distribue une librairie javascript permettant de parser ce fichier et de générer une base de données SQLite. Base qui serait, elle, facilement exploitable. Voir https://github.com/BaseAdresseNationale/fantoir

Je pense qu'on pourrait procéder de la manière suivante:

  1. Générer un BDD SQLite en utilisant la librairie de l'Etalab.
  2. Créer un endpoint JSON dans l'application Flask permettant de rechercher le code Insee en fonction d'un nom partiel de commune en utilisant les données issues de la base SQLite. Voir les extentions FTS5 https://www.sqlite.org/fts5.html implémentées par SQLite.
  3. Créer un endpoint JSON dans l'application Flask permettant de rechercher un code RIVOLI en fonction d'un nom de voie partiel + un nom de commune. Toujours en utilisant les données issues de la base SQLite et FTS5.

D'un point de vue HTTP, on se retrouverait avec ces deux nouveaux endpoints exposés par l'application Flask:

GET /geo/fantoir/INSEE/${query commune} => [CODE_INSEE]
GET /geo/fantoir/RIVOLI/${CODE_INSEE}/${query voie} => [CODE_RIVOLI]

Il faudra ensuite créer le formulaire permettant a l'utilisateur de récupérer/entrer les données necessaires pour faire l'appel sur l'API d'Axione décrite plus haut. Idéalement, il faudrait que l'autocomplete du formulaire fonctionne également sans Javascript.

Pour le moment, nous ne supportons le test d'éligibilité que via un numéro de PTO. Ce qui est assez limité étant donné que dans pas mal de cas, on peut se retrouver avec un logement éligible à l'offre Axione mais n'ayant jamais été raccordé au réseau fibre, et donc ne possédant pas encore de PTO. L'API [interop-fibre](https://www.interop-fibre.fr/wp-content/uploads/2014/09/2021-06-21-webservice-aide-prise-commande.zip) nous propose d'utiliser 3 différents référentiels géographiques pour faire une recherche d'éligibilité: 1. Hexaclé. 1. BAN. 1. RIVOLI (code issu du référentiel FANTOIR). Hexaclé est un référentiel propriétaire appartenant à la poste, nous n'y avons pas accès. Le référentiel BAN, bien que présent dans l'interface du webservice, n'est pas encore implémenté par Axione. Voir le thread e-mail https://listes.aquilenet.fr/arc/admin-ftth-axione/2021-09/msg00145.html pour plus d'infos. Ça nous laisse avec pour seule option le codage RIVOLI. Si on regarde le WSDL de description du webservice, on voit qu'on aura besoin des champs suivants pour la requête: ```xml <xs:complexType name='ReferenceRivoliType'> <xs:attribute use='required' name='codeInsee' type='xs:string'/> <xs:attribute use='required' name='codeRivoli' type='xs:string'/> <xs:attribute use='required' name='numeroVoie' type='xs:nonNegativeInteger'/> <xs:attribute use='optional' name='complementNumeroVoie' type='xs:string' /> </xs:complexType> ``` Toutes ces données sont issues du [fichier FANTOIR](https://www.data.gouv.fr/fr/datasets/fichier-fantoir-des-voies-et-lieux-dits/). Ce fichier est librement disponible, mis a disposition par data.gouv.fr. En revanche, contrairement a BAN, il ne semble pas y avoir d'API en ligne nous permettant de facilement exploiter ces données. Nous allons devoir faire ça nous-même. Le fichier FANTOIR est distribué sous la forme d'un fichier texte plat, il n'est pas directement exploitable tel quel. Bonne nouvelle: l'Etalab distribue une librairie javascript permettant de parser ce fichier et de générer une base de données SQLite. Base qui serait, elle, facilement exploitable. Voir https://github.com/BaseAdresseNationale/fantoir Je pense qu'on pourrait procéder de la manière suivante: 1. Générer un BDD SQLite en utilisant la librairie de l'Etalab. 2. Créer un endpoint JSON dans l'application Flask permettant de rechercher le code Insee en fonction d'un nom partiel de commune en utilisant les données issues de la base SQLite. Voir les extentions FTS5 https://www.sqlite.org/fts5.html implémentées par SQLite. 3. Créer un endpoint JSON dans l'application Flask permettant de rechercher un code RIVOLI en fonction d'un nom de voie partiel + un nom de commune. Toujours en utilisant les données issues de la base SQLite et FTS5. D'un point de vue HTTP, on se retrouverait avec ces deux nouveaux endpoints exposés par l'application Flask: ``` GET /geo/fantoir/INSEE/${query commune} => [CODE_INSEE] GET /geo/fantoir/RIVOLI/${CODE_INSEE}/${query voie} => [CODE_RIVOLI] ``` Il faudra ensuite créer le formulaire permettant a l'utilisateur de récupérer/entrer les données necessaires pour faire l'appel sur l'API d'Axione décrite plus haut. Idéalement, il faudrait que l'autocomplete du formulaire fonctionne également sans Javascript.
felix.baylac self-assigned this 2021-10-23 14:21:03 +02:00

Pour télécharger le dernier fichier FANTOIR zippé:

wget -O fantoir.zip $(curl https://www.data.gouv.fr/api/1/datasets/fichier-fantoir-des-voies-et-lieux-dits/ | jq -r '.resources[] |objects | .url' | grep "_zip" | tail -1 )

ça pourra servir si on veut faciliter les mises à jours. En ajoutant des checks sur la date car là on présume que le dernier de la liste c'est le fichier le plus récent (ce qui est le cas aujourd'hui.

Pour télécharger le dernier fichier FANTOIR zippé: ``` wget -O fantoir.zip $(curl https://www.data.gouv.fr/api/1/datasets/fichier-fantoir-des-voies-et-lieux-dits/ | jq -r '.resources[] |objects | .url' | grep "_zip" | tail -1 ) ``` ça pourra servir si on veut faciliter les mises à jours. En ajoutant des checks sur la date car là on présume que le dernier de la liste c'est le fichier le plus récent (ce qui est le cas aujourd'hui.
Author
Member

Le format de la DB générée par https://github.com/BaseAdresseNationale/fantoir est assez foireux. C'est une seule table clé/value ayant pour clé les codes INSEE, pour value un JSON contenant toutes les voies de la commune. Bref, pas top.


J'ai essayé de faire une requête en utilisant cette base de données malheureusement sans succès.

A partir de mon adresse, pour laquelle j'ai réussi a trouver le code rivoli a l'aide d'une la base de données SQLite et d'un peu de magie jq:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ent="http://structureadresseftth.axione.fr/model/entreprise" xmlns:com="http://structureadresseftth.axione.fr/model/commun">
   <soapenv:Header/>
   <soapenv:Body>
      <ent:obtentionStructureAdresseDemandeSoap>
         <ent:entete versionWS="3.0" horodatageRequete="2021-08-12T17:07:00.000+01:00">
            <com:operateurCommercial nom="AQUILENET" identifiant=""/>
         </ent:entete>
         <ent:referenceAdresse>
                 <ent:referenceRivoli codeInsee="64102" codeRivoli="0790" numeroVoie="10"/>
         </ent:referenceAdresse>
      </ent:obtentionStructureAdresseDemandeSoap>
   </soapenv:Body>
</soapenv:Envelope>

L'API me retourne invariablement un

<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"><SOAP-ENV:Header/><SOAP-ENV:Body><ns3:obtentionStructureAdresseReponseSoap xmlns:ns2="http://structureadresseftth.axione.fr/model/commun" xmlns:ns3="http://structureadresseftth.axione.fr/model/entreprise"><ns3:entete horodatageReponse="2021-10-31T18:16:56.569+01:00" horodatageRequete="2021-08-12T17:07:00.000+01:00" identifiantReponse="1635700616569" versionWS="3.0"><ns2:operateurCommercial identifiant="" nom="AQUILENET"/></ns3:entete><ns3:codeRetour><ns2:codeRetour>1</ns2:codeRetour><ns2:codeErreur>C05</ns2:codeErreur><ns2:libelleErreur>Recherche multicritères non supportée</ns2:libelleErreur></ns3:codeRetour><ns3:codeOI/></ns3:obtentionStructureAdresseReponseSoap></SOAP-ENV:Body></SOAP-ENV:Envelope>

Qui semble être une erreur générique de leur côté...

Le format de requête ne semble pas coller a 100% a interop' fibre pour les requêtes PTO et Hexaclé. Le code PTO/Hexaclé est supposé être mis dans un nœud XML et non pas comme attribut du nœud referenceAdresse.

Bref, ça coince un peu. J'ai l'impression que ma requête n'est pas correctement formatée.

Le format de la DB générée par https://github.com/BaseAdresseNationale/fantoir est assez foireux. C'est une seule table clé/value ayant pour clé les codes INSEE, pour value un JSON contenant **toutes** les voies de la commune. Bref, pas top. ------------------------------- J'ai essayé de faire une requête en utilisant cette base de données malheureusement sans succès. A partir de mon adresse, pour laquelle j'ai réussi a trouver le code rivoli a l'aide d'une la base de données SQLite et d'un peu de magie `jq`: ```xml <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ent="http://structureadresseftth.axione.fr/model/entreprise" xmlns:com="http://structureadresseftth.axione.fr/model/commun"> <soapenv:Header/> <soapenv:Body> <ent:obtentionStructureAdresseDemandeSoap> <ent:entete versionWS="3.0" horodatageRequete="2021-08-12T17:07:00.000+01:00"> <com:operateurCommercial nom="AQUILENET" identifiant=""/> </ent:entete> <ent:referenceAdresse> <ent:referenceRivoli codeInsee="64102" codeRivoli="0790" numeroVoie="10"/> </ent:referenceAdresse> </ent:obtentionStructureAdresseDemandeSoap> </soapenv:Body> </soapenv:Envelope> ``` L'API me retourne invariablement un ```xml <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"><SOAP-ENV:Header/><SOAP-ENV:Body><ns3:obtentionStructureAdresseReponseSoap xmlns:ns2="http://structureadresseftth.axione.fr/model/commun" xmlns:ns3="http://structureadresseftth.axione.fr/model/entreprise"><ns3:entete horodatageReponse="2021-10-31T18:16:56.569+01:00" horodatageRequete="2021-08-12T17:07:00.000+01:00" identifiantReponse="1635700616569" versionWS="3.0"><ns2:operateurCommercial identifiant="" nom="AQUILENET"/></ns3:entete><ns3:codeRetour><ns2:codeRetour>1</ns2:codeRetour><ns2:codeErreur>C05</ns2:codeErreur><ns2:libelleErreur>Recherche multicritères non supportée</ns2:libelleErreur></ns3:codeRetour><ns3:codeOI/></ns3:obtentionStructureAdresseReponseSoap></SOAP-ENV:Body></SOAP-ENV:Envelope> ``` Qui semble être une erreur générique de leur côté... Le format de requête ne semble pas coller a 100% a interop' fibre pour les requêtes PTO et Hexaclé. Le code PTO/Hexaclé est supposé être mis dans un nœud XML et non pas comme attribut du nœud `referenceAdresse`. Bref, ça coince un peu. J'ai l'impression que ma requête n'est pas correctement formatée.
Author
Member

Requête FANTOIR fonctionelle:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ent="http://structureadresseftth.axione.fr/model/entreprise" xmlns:com="http://structureadresseftth.axione.fr/model/commun">
   <soapenv:Header/>
   <soapenv:Body>
      <ent:obtentionStructureAdresseDemandeSoap>
         <ent:entete versionWS="3.0" horodatageRequete="2021-08-12T17:07:00.000+01:00">
            <com:operateurCommercial nom="AQUILENET" identifiant=""/>
         </ent:entete>
         <ent:referenceAdresse>
                 <com:referenceRivoli codeInsee="64445" codeRivoli="2832" numeroVoie="64"/>
         </ent:referenceAdresse>
      </ent:obtentionStructureAdresseDemandeSoap>
   </soapenv:Body>
</soapenv:Envelope>
Requête FANTOIR fonctionelle: ```xml <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ent="http://structureadresseftth.axione.fr/model/entreprise" xmlns:com="http://structureadresseftth.axione.fr/model/commun"> <soapenv:Header/> <soapenv:Body> <ent:obtentionStructureAdresseDemandeSoap> <ent:entete versionWS="3.0" horodatageRequete="2021-08-12T17:07:00.000+01:00"> <com:operateurCommercial nom="AQUILENET" identifiant=""/> </ent:entete> <ent:referenceAdresse> <com:referenceRivoli codeInsee="64445" codeRivoli="2832" numeroVoie="64"/> </ent:referenceAdresse> </ent:obtentionStructureAdresseDemandeSoap> </soapenv:Body> </soapenv:Envelope> ```

Pour le dev de la recherche d'adresse j'ai ajouté à la base sqlite Fantoir les données insee sur les communes de la poste (laposte_hexasmal
Pour faire un import du csv de la poste j'ai dû y apporter quelques modifs comme il n'est pas au format standard csv (';' au lieu de ','), sur le fichier j'ai donc remplacer avec sed ; par , et dans l'entête ajouté une colonne ,coordonnee s_gps_y (et oui les coordonnees GPS sont séparées par une ',')

Une fois fait cela dans la base sqlite fantoir j'ai fait .import --csv path/to/laposte_hexasmal.csv insee pour créer la table insee.

J'ai ajouté 2 endpoints qui renvoient chacun un tableau JSON:

  • /addresses/communes?s=<zip ou nom commune>
    • Si pas de paramètre 's' alors on renvoie toutes les communes
  • /addresses/fantoirvoies/<codeInsee>

cf. felix.baylac/axione-elig-test#8

Pour le dev de la recherche d'adresse j'ai ajouté à la base sqlite Fantoir les données insee sur les communes de la poste ([laposte_hexasmal](https://datanova.laposte.fr/explore/dataset/laposte_hexasmal/information/?disjunctive.code_commune_insee&disjunctive.nom_de_la_commune&disjunctive.code_postal&disjunctive.ligne_5) Pour faire un import du csv de la poste j'ai dû y apporter quelques modifs comme il n'est pas au format standard csv (';' au lieu de ','), sur le fichier j'ai donc remplacer avec sed ; par , et dans l'entête ajouté une colonne `,coordonnee s_gps_y` (et oui les coordonnees GPS sont séparées par une ',') Une fois fait cela dans la base sqlite fantoir j'ai fait `.import --csv path/to/laposte_hexasmal.csv insee` pour créer la table insee. J'ai ajouté 2 endpoints qui renvoient chacun un tableau JSON: - `/addresses/communes?s=<zip ou nom commune>` - Si pas de paramètre 's' alors on renvoie toutes les communes - `/addresses/fantoirvoies/<codeInsee>` cf. https://forge.aquilenet.fr/felix.baylac/axione-elig-test/pulls/8
Author
Member

Cool!

Pour faire un import du csv de la poste j'ai dû y apporter quelques modifs comme il n'est pas au format standard csv (';' au lieu de ','), sur le fichier j'ai donc remplacer avec sed ; par , et dans l'entête ajouté une colonne ,coordonnee s_gps_y (et oui les coordonnees GPS sont séparées par une ',')

Ça marche. Pour info, tu peux faire tout ça directement dans SQlite via:

SQLite version 3.36.0 2021-06-18 18:36:39
Enter ".help" for usage hints.
Connected to a transient in-memory database.
Use ".open FILENAME" to reopen on a persistent database.
sqlite> .separator ;
sqlite> .import laposte_hexasmal.csv code_insee
sqlite> select * from code_insee limit 1;
02547;LA NEUVILLE HOUSSET;02250;;LA NEUVILLE HOUSSET;49.7881379377,3.73171627307
sqlite> .schema code_insee
CREATE TABLE IF NOT EXISTS "code_insee"(
  "Code_commune_INSEE" TEXT,
  "Nom_commune" TEXT,
  "Code_postal" TEXT,
  "Ligne_5" TEXT,
  "Libellé_d_acheminement" TEXT,
  "coordonnees_gps" TEXT
);
Cool! > Pour faire un import du csv de la poste j'ai dû y apporter quelques modifs comme il n'est pas au format standard csv (';' au lieu de ','), sur le fichier j'ai donc remplacer avec sed ; par , et dans l'entête ajouté une colonne ,coordonnee s_gps_y (et oui les coordonnees GPS sont séparées par une ',') Ça marche. Pour info, tu peux faire tout ça directement dans SQlite via: ``` SQLite version 3.36.0 2021-06-18 18:36:39 Enter ".help" for usage hints. Connected to a transient in-memory database. Use ".open FILENAME" to reopen on a persistent database. sqlite> .separator ; sqlite> .import laposte_hexasmal.csv code_insee sqlite> select * from code_insee limit 1; 02547;LA NEUVILLE HOUSSET;02250;;LA NEUVILLE HOUSSET;49.7881379377,3.73171627307 sqlite> .schema code_insee CREATE TABLE IF NOT EXISTS "code_insee"( "Code_commune_INSEE" TEXT, "Nom_commune" TEXT, "Code_postal" TEXT, "Ligne_5" TEXT, "Libellé_d_acheminement" TEXT, "coordonnees_gps" TEXT ); ```
Sign in to join this conversation.
No labels
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: Aquilenet/axione-elig-test#1
No description provided.