Newer
Older
const soapRequest = require('easy-soap-request')
const moment = require('moment')
require('moment-timezone')
const xml2js = require('xml2js')
moment.locale('fr') // set the language
moment.tz.setDefault('Europe/Paris') // set the timezone
/*** Connector Constants ***/
const manualExecution =
process.env.COZY_JOB_MANUAL_EXECUTION === 'true' ? true : false
? moment().subtract(12, 'month')
: moment().subtract(6, 'month')
let startDailyDateString = startDailyDate.format('YYYY-MM-DD')
// const startLoadDate = moment().subtract(7, 'day')
// const startLoadDateString = startLoadDate.format('YYYY-MM-DD')
const endDate = moment()
const endDateString = endDate.format('YYYY-MM-DD')
module.exports = new BaseKonnector(start)
// The start function is run by the BaseKonnector instance only when it got all the account
// information (fields). When you run this connector yourself in "standalone" mode or "dev" mode,
// the account information come from ./konnector-dev-config.json file
// cozyParameters are static parameters, independents from the account. Most often, it can be a
// secret api key.
async function start(fields, cozyParameters) {
log('info', 'Gathering data ...')
let baseUrl = fields.wso2BaseUrl
let apiAuthKey = fields.apiToken
let loginUtilisateur = fields.loginUtilisateur
if (cozyParameters && Object.keys(cozyParameters).length !== 0) {
log('debug', 'Found COZY_PARAMETERS')
baseUrl = cozyParameters.secret.wso2BaseUrl
apiAuthKey = cozyParameters.secret.apiToken
loginUtilisateur = cozyParameters.secret.loginUtilisateur
}
//TODO: authentification ?
await getDataStartDate(
`${baseUrl}/enedis_SGE_ConsultationDonneesTechniquesContractuelles/1.0`,
apiAuthKey,
loginUtilisateur,
fields.pointId
)
await getData(
`${baseUrl}/enedis_SGE_ConsultationMesuresDetaillees/1.0`,
apiAuthKey,
loginUtilisateur,
fields.pointId
)
log('info', 'Konnector process end')
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
/**
*
* @param {string} url
* @param {string} apiAuthKey
* @param {string} userLogin
* @param {number} pointId
*/
async function getDataStartDate(url, apiAuthKey, userLogin, pointId) {
log('info', 'Fetching data start date')
const sampleHeaders = {
'Content-Type': 'text/xml;charset=UTF-8',
apikey: apiAuthKey,
}
const { response } = await soapRequest({
url: url,
headers: sampleHeaders,
xml: userTechnicalData(pointId, userLogin),
}).catch(err => {
log('error', 'technicalDataResponse')
log('error', err)
return err
})
xml2js.parseString(
response.body,
{
tagNameProcessors: [parseTags],
valueProcessors: [parseValue],
explicitArray: false,
},
processStartDate()
)
}
/**
*
* @param {string} url
* @param {string} apiAuthKey
* @param {string} userLogin
* @param {number} pointId
*/
async function getData(url, apiAuthKey, userLogin, pointId) {
log('info', 'Fetching data')
const sampleHeaders = {
'Content-Type': 'text/xml;charset=UTF-8',
apikey: apiAuthKey,
}
const { response } = await soapRequest({
url: url,
headers: sampleHeaders,
xml: userMesureDetailles(
pointId,
userLogin,
startDailyDateString,
endDateString
),
}).catch(err => {
tagNameProcessors: [parseTags],
valueProcessors: [parseValue],
explicitArray: false,
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
/**
* Format tag in order to be manipulated easly
* @param {string} name
* @returns {string} name
*/
function parseTags(name) {
if (name.split(':')[1] !== undefined) {
return name.split(':')[1]
}
return name
}
/**
*
* @param {string} value
* @param {string} name
* @returns {string|number} value
*/
function parseValue(value, name) {
// Wh => KWh
if (name === 'v') {
return parseFloat((parseInt(value) / 1000).toFixed(2))
}
return value
}
/**
* Parse data
*/
function processData() {
return async (err, result) => {
if (err) {
log('error', err)
throw err
}
// Return only needed part of info
const data = parseSgeXmlData(result)
return storeData(
await formateDataForDoctype(data),
'com.grandlyon.enedis.day',
['year', 'month', 'day']
)
}
}
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
/**
* Parse data
*/
function processStartDate() {
return async (err, result) => {
if (err) {
log('error', err)
throw err
}
// update start Date with contract openning date
startDailyDate = moment(parseSgeXmlTechnicalData(result), 'YYYY-MM-DD')
startDailyDateString = startDailyDate.format('YYYY-MM-DD')
}
}
/**
* Return start date
* @param {string} result
* @returns {string}
*/
function parseSgeXmlTechnicalData(result) {
log('info', 'Parsing technical data')
let json = JSON.stringify(result)
return JSON.parse(json)['Envelope']['Body'][
'consulterDonneesTechniquesContractuellesResponse'
]['point']['donneesGenerales'][
'dateDerniereModificationFormuleTarifaireAcheminement'
]
}
* @returns {SGEData[]}
*/
function parseSgeXmlData(result) {
log('info', 'Parsing list of documents')
let json = JSON.stringify(result)
return JSON.parse(json)['Envelope']['Body'][
'consulterMesuresDetailleesResponse'
]['grandeur']['mesure']
}
/**
* Save data in the right doctype db and prevent duplicated keys
* @param {EnedisKonnectorData[]} data
* @param {string} doctype
* @param {string[]} filterKeys
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
*/
async function storeData(data, doctype, filterKeys) {
log('debug', doctype, 'Store into')
const filteredDocuments = await hydrateAndFilter(data, doctype, {
keys: filterKeys,
})
return await addData(filteredDocuments, doctype)
}
/**
* Query SGE in order to get info
* @param {number} pointId
* @param {string} userLogin
* @param {string} startDt
* @param {string} endDt
* @returns {string}
*/
function userMesureDetailles(pointId, userLogin, startDt, endDt) {
log('info', `Query data between ${startDt} and ${endDt}`)
return `<?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>${userLogin}</initiateurLogin>
<pointId>${pointId}</pointId>
<mesuresTypeCode>ENERGIE</mesuresTypeCode>
<grandeurPhysique>EA</grandeurPhysique>
<soutirage>true</soutirage>
<injection>false</injection>
<dateDebut>${startDt}</dateDebut>
<dateFin>${endDt}</dateFin>
<mesuresCorrigees>false</mesuresCorrigees>
<accordClient>true</accordClient>
</demande>
</v2:consulterMesuresDetaillees>
</soapenv:Body>
</soapenv:Envelope>
`
}
/**
* Get user technical data
* @param {string} pointId
* @param {string} userLogin
* @returns {string}
*/
function userTechnicalData(pointId, userLogin) {
log('info', `Query userMesureDetailles`)
return `<?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>${userLogin}</loginUtilisateur>
<autorisationClient>true</autorisationClient>
</v2:consulterDonneesTechniquesContractuelles>
</soapenv:Body>
</soapenv:Envelope>
`
}
/**
* Format data for DB storage
* @param {SGEData[]} data
* @returns {Promise<EnedisKonnectorData[]>} Parsed timestamp array
*/
async function formateDataForDoctype(data) {
log('info', 'Formating data')
// record
return data.map(record => {
let date = moment(record.d, 'YYYY/MM/DD h:mm:ss')
return {
load: record.v,
year: parseInt(date.format('YYYY')),
month: parseInt(date.format('M')),
day: parseInt(date.format('D')),
hour: parseInt(date.format('H')),
minute: parseInt(date.format('m')),
}
})