# Enedis SGE Konnector This konnector fetches consumption measures from Enedis SGE SOAP API. You should also check Cozy's official documentations for konnectors : https://docs.cozy.io/en/tutorials/konnector/getting-started ## Enedis context The API used by this konnector are the one used by all energy providers (edf, total...), this one is supposed to have a high availability. Contrary to enedis oauth konnector, this is a regular auth konnector. ## Technical overview ### Lib used - xml2js: Lib allowing easy parsing to json - easy-soap-request: Lib making soap request ### WSO2 For now enedis API are proxied by WSO2 api manager. You can find documentation and devportal [here](https://apis.grandlyon.fr/devportal). ### Scaffolding - core/types: contains jsdoc types - core/: requests wrapper with error handling logic - helpers/ : contains helpers for aggregation, env and parsing - requests/: contain all methods for : Parsing sge requests, Send/get backoffice data, interactions with cozy stack - index.js: main file where default konnector methods are launch (start, ...) - onDeleteAccount.js: hold consent suppression when a user delete an account. Automatically launched on delete. ### ts-check In order to have better comfort while coding, we have enable ts-checking with vs-code. The verification is based on js-doc, please take time to maintain the js-doc. :::info ts-check The ts-check is none blocking. It will only put information in vs-code ide. ::: ### Local dev In order to local test you have to copy the [konnector-dev-config.example.json](https://forge.grandlyon.com/web-et-numerique/factory/llle_project/enedis-sge-konnector/-/blob/dev/konnector-dev-config.example.json?ref_type=heads) to `konnector-dev-config.json` and replace values and corresponding secrets. :::warning user consent While running in dev mode, be sure to have user consent, either on production env or with enedis standard form. ::: You can now run the following commands to run the konnector : ```sh yarn standalone # Run inside shell with no cozy env dependencies yarn standalone-no-data # Run inside shell without getting any data yarn dev # Run with your local cozy. For this one you need local stack to run yarn onDeleteAccount:standalone # Run onDeleteAccount script yarn onDeleteAccount # Run onDeleteAccount script with real cozy ``` For standalone cmd you can find konnector results in `/data/importedData.json` ### Konnector Methods | Method | Description | | ------ | ------ | | start | Main method of konnector. Handle global flow and init method with provided params | | gatherData | Wrapper for getting daily, half-hour and max power data | | getData | Get daily data | | getMaxPowerData | Get daily Max Power data | | getHalfHourData | Get half-hour data | | getOffPeakHours | Get off-peak hours if activated in contract and store them in cozy.account | | processData | Given a doctype, parse and format data before storing and aggregating | | setStartDate | Save startDate with the right time range | | storeData | Save data to user's cozy | | agregateMonthAndYearData | Sum daily data for months and years | | isFirstStart | Check if it's first start or an alternate start base on boId in cozy.account | ## Dataflow ### Overview Functional and technical flow chart: [Lien du schema](https://whimsical.com/sge-tech-DxbYM8DdajRjTr6WZat1bV) ### Authentication Information required: - Name - Surname - PointID (PDL) - Full address - Postal Code - City #### Test with user invoices To test user invoices, you will have to make a copy of `konnector-dev-config.example.json` to `konnector-dev-config.json` and fill out informations. Then, to test the authentication flow of the konnector without fetching any data, launch the script `yarn standalone-no-data` ### Fetch Data In order to get data from the SGE API we have to request the following route : #### Get user contract startDate Method : **POST** Data Route : **enedis_SGE_ConsultationDonneesTechniquesContractuelles/1.0** ```xml <soapenv:Body> <v2:consulterDonneesTechniquesContractuelles> <pointId>${pointId}</pointId> <loginUtilisateur>${userLogin}</loginUtilisateur> <autorisationClient>true</autorisationClient> </v2:consulterDonneesTechniquesContractuelles> </soapenv:Body> ``` #### Get daily data and Get Half-hour data Method : **POST** Data Route : **enedis_SGE_ConsultationMesuresDetaillees/1.0** ```xml <?xml version='1.0' encoding='utf-8'?> <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:v2="http://www.enedis.fr/sge/b2b/services/consultationmesuresdetaillees/v2.0" xmlns:v1="http://www.enedis.fr/sge/b2b/technique/v1.0"> <soapenv:Header/> <soapenv:Body> <v2:consulterMesuresDetaillees> <demande> <initiateurLogin>${appLogin}</initiateurLogin> <pointId>${pointId}</pointId> <mesuresTypeCode>${mesureType}</mesuresTypeCode> <grandeurPhysique>${unit}</grandeurPhysique> <soutirage>true</soutirage> <injection>false</injection> <dateDebut>${startDate}</dateDebut> <dateFin>${endDate}</dateFin> <mesuresCorrigees>false</mesuresCorrigees> <accordClient>true</accordClient> </demande> </v2:consulterMesuresDetaillees> </soapenv:Body> </soapenv:Envelope> ``` #### Get Max Power data Method : **POST** Data Route : **enedis_SGE_ConsultationMesuresDetaillees/1.0** ```xml <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:v2="http://www.enedis.fr/sge/b2b/services/consultationmesuresdetaillees/v2.0" xmlns:v1="http://www.enedis.fr/sge/b2b/technique/v1.0"> <soapenv:Header/> <soapenv:Body> <v2:consulterMesuresDetaillees> <demande> <initiateurLogin>${appLogin}</initiateurLogin> <pointId>${pointId}</pointId> <mesuresTypeCode>${mesureType}</mesuresTypeCode> <grandeurPhysique>${unit}</grandeurPhysique> <soutirage>true</soutirage> <injection>false</injection> <dateDebut>${startDate}</dateDebut> <dateFin>${endDate}</dateFin> <mesuresPas>P1D</mesuresPas> <mesuresCorrigees>false</mesuresCorrigees> <accordClient>true</accordClient> </demande> </v2:consulterMesuresDetaillees> </soapenv:Body> </soapenv:Envelope> ``` #### Get contract information Method : **POST** Data Route : **enedis_SGE_enedis_SGE_ConsultationDonneesTechniquesContractuelles/1.0** This route also gives off-peak hours, if the user chose a contract with off-peak hours ```xml <?xml version='1.0' encoding='utf-8'?> <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:v2="http://www.enedis.fr/sge/b2b/services/consulterdonneestechniquescontractuelles/v1.0" xmlns:v1="http://www.enedis.fr/sge/b2b/technique/v1.0"> <soapenv:Header/> <soapenv:Body> <v2:consulterDonneesTechniquesContractuelles> <pointId>${pointId}</pointId> <loginUtilisateur>${appLogin}</loginUtilisateur> <autorisationClient>true</autorisationClient> </v2:consulterDonneesTechniquesContractuelles> </soapenv:Body> </soapenv:Envelope> ``` Response : ```xml <point id="12345678912345"> <donneesGenerales> <etatContractuel code="SERVC"> <libelle>En service</libelle> </etatContractuel> <adresseInstallation> <numeroEtNomVoie>208 BIS RUE GARIBALDI</numeroEtNomVoie> <codePostal>69003</codePostal> <commune code="69383"> <libelle>LYON 3</libelle> </commune> </adresseInstallation> <niveauOuvertureServices>2</niveauOuvertureServices> </donneesGenerales> <situationComptage> <dispositifComptage> <relais> <plageHeuresCreuses>HC (22H00-6H00)</plageHeuresCreuses> </relais> </dispositifComptage> </situationComptage> </point> ``` #### Get user PDL Method : **POST** Data Route : **enedis_SGE_RechercheServicesMesures/1.0** ```xml <?xml version='1.0' encoding='utf-8'?> <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:v2="http://www.enedis.fr/sge/b2b/services/rechercherpoint/v2.0" xmlns:v1="http://www.enedis.fr/sge/b2b/technique/v1.0"> <soapenv:Header/> <soapenv:Body> <v2:rechercherPoint> <criteres> <adresseInstallation> <numeroEtNomVoie>${address}</numeroEtNomVoie> <codePostal>${postalCode}</codePostal> <codeInseeCommune>${inseeCode}</codeInseeCommune> </adresseInstallation> <nomClientFinalOuDenominationSociale>${name}</nomClientFinalOuDenominationSociale> <rechercheHorsPerimetre>true</rechercheHorsPerimetre> </criteres> <loginUtilisateur>${appLogin}</loginUtilisateur> </v2:rechercherPoint> </soapenv:Body> </soapenv:Envelope> ``` #### Get User services subscriptions Method : **POST** Data Route : **enedis_SGE_RechercheServicesMesures/1.0** ```xml <?xml version='1.0' encoding='utf-8'?> <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:v2="http://www.enedis.fr/sge/b2b/rechercherservicessouscritsmesures/v1.0" xmlns:v1="http://www.enedis.fr/sge/b2b/technique/v1.0"> <soapenv:Header/> <soapenv:Body> <v2:rechercherServicesSouscritsMesures> <criteres> <pointId>${pointId}</pointId> <contratId>${contractId}</contratId> </criteres> <loginUtilisateur>${appLogin}</loginUtilisateur> </v2:rechercherServicesSouscritsMesures> </soapenv:Body> </soapenv:Envelope> ``` #### Start user contract Method : **POST** Data Route : **enedis_SGE_CommandeCollectePublicationMesures/1.0** ```xml <?xml version='1.0' encoding='utf-8'?> <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:v2="http://www.enedis.fr/sge/b2b/commandercollectepublicationmesures/v3.0" xmlns:v1="http://www.enedis.fr/sge/b2b/technique/v1.0"> <soapenv:Header/> <soapenv:Body> <v2:commanderCollectePublicationMesures> <demande> <donneesGenerales> <objetCode>AME</objetCode> <pointId>${pointId}</pointId> <initiateurLogin>${appLogin}</initiateurLogin> <contratId>${contractId}</contratId> </donneesGenerales> <accesMesures> <dateDebut>${startDate}</dateDebut> <dateFin>${endDate}</dateFin> <declarationAccordClient> <accord>true</accord> <personnePhysique> <nom>${name}</nom> </personnePhysique> </declarationAccordClient> <mesuresTypeCode>CDC</mesuresTypeCode> <soutirage>true</soutirage> <injection>false</injection> <mesuresPas>PT30M</mesuresPas> <mesuresCorrigees>false</mesuresCorrigees> <transmissionRecurrente>true</transmissionRecurrente> <periodiciteTransmission>P1D</periodiciteTransmission> </accesMesures> </demande> </v2:commanderCollectePublicationMesures> </soapenv:Body> </soapenv:Envelope> ``` #### Stop User contract ```xml <?xml version='1.0' encoding='utf-8'?> <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:v2="http://www.enedis.fr/sge/b2b/commanderarretservicesouscritmesures/v1.0" xmlns:v1="http://www.enedis.fr/sge/b2b/technique/v1.0"> <soapenv:Header/> <soapenv:Body> <v2:commanderArretServiceSouscritMesures> <demande> <donneesGenerales> <objetCode>ASS</objetCode> <pointId>${pointId}</pointId> <initiateurLogin>${appLogin}</initiateurLogin> <contratId>${contractId}</contratId> </donneesGenerales> <arretServiceSouscrit> <serviceSouscritId>${serviceSouscritId}</serviceSouscritId> </arretServiceSouscrit> </demande> </v2:commanderArretServiceSouscritMesures> </soapenv:Body> </soapenv:Envelope> ``` The same endpoint is used to get the data. The soap body is the following: Method : **POST** Data Route : **enedis_SGE_ConsultationDonneesTechniquesContractuelles/1.0** ```xml <soapenv:Body> <v2:consulterMesuresDetaillees> <demande> <initiateurLogin>${userLogin}</initiateurLogin> <pointId>${pointId}</pointId> <mesuresTypeCode>${mesureType}</mesuresTypeCode> <grandeurPhysique>${unit}</grandeurPhysique> <soutirage>true</soutirage> <injection>false</injection> <dateDebut>${startDt}</dateDebut> <dateFin>${endDt}</dateFin> <mesuresCorrigees>false</mesuresCorrigees> <accordClient>true</accordClient> </demande> </v2:consulterMesuresDetaillees> </soapenv:Body> ``` ### Known Issues #### Contract deletion and creation on same day If you stop a contract on a day, (for exemple 8/08/22), you cannot start a new contract for this date with [start contract route](./enedis-sge.md#user_contract_start). You have to wait for the next day. This might cause some production issues #### User data collect opposition Users can remove consent from enedis account on data collecting. This will return the following when checking contracts. ```xml <serviceSouscritMesures> <serviceSouscritId>74472322</serviceSouscritId> <pointId>19176410771132</pointId> <serviceSouscritType code="OPPENR"/> <serviceSouscritLibelle>Opposition à l'enregistrement de la courbe de charge</serviceSouscritLibelle> <injection>false</injection> <soutirage>true</soutirage> <etatCode>ACTIF</etatCode> <dateDebut>2022-06-24+02:00</dateDebut> <dateFin>2022-08-10+02:00</dateFin> <motifFinLibelle>Arrêt par le client</motifFinLibelle> </serviceSouscritMesures> ``` We cannot override that, the only solution is to tell the user to activate data collect on [enedis](https://mon-compte-particulier.enedis.fr/donnees/).