Newer
Older
const {
BaseKonnector,
log,
errors,
addData,
hydrateAndFilter,
cozyClient
const rp = require('request-promise')
const moment = require('moment')
require('moment-timezone')
moment.locale('fr') // set the language
moment.tz.setDefault('Europe/Paris') // set the timezone
const manualExecution =
process.env.COZY_JOB_MANUAL_EXECUTION === 'true' ? true : false
? moment().subtract(1, 'year').format('MM/DD/YYYY')
: moment().subtract(3, 'year').format('MM/DD/YYYY')
const endDate = moment().format('MM/DD/YYYY')
// const timeRange = ['day', 'month', 'year']
// 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
async function start(fields, cozyParameters) {
try {
// resetting data for demo only
// await resetData()
// const baseUrl = fields.eglBaseURL
// const apiAuthKey = fields.eglAPIAuthKey
const baseUrl = cozyParameters.secret.eglBaseURL
const apiAuthKey = cozyParameters.secret.eglAPIAuthKey
log('info', 'Authenticating ...')
const response = await authenticate(
fields.login,
fields.password,
baseUrl,
apiAuthKey
)
log('info', 'Successfully logged in')
const eglData = await getData(response, baseUrl, apiAuthKey)
if (eglData) {
log('debug', 'Process egl daily data')
const processedLoadData = await processData(
eglData,
rangeDate.day.doctype,
rangeDate.day.keys
log('debug', 'Agregate egl load data for month and year')
await agregateMonthAndYearData(processedLoadData)
} else {
log('debug', 'No data found')
}
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
/**
* Parse data
* Remove existing data from DB using hydrateAndFilter
* Store filtered data
* Return the list of filtered data
*/
async function processData(data, doctype, filterKeys) {
// const formatedData = await formateData(data)
log('debug', 'processData - data formated')
// Remove data for existing days into the DB
const filteredData = await hydrateAndFilter(data, doctype, {
keys: filterKeys
})
log('debug', 'processData - data filtered')
// Store new day data
await storeData(filteredData, doctype, filterKeys)
return filteredData
}
/**
* Agregate data from daily data to monthly and yearly data
*/
async function agregateMonthAndYearData(data) {
// Sum year and month values into object with year or year-month as keys
if (data && data.length !== 0) {
let monthData = {}
let yearData = {}
data.forEach(element => {
element.year + '-' + element.month in monthData
? (monthData[element.year + '-' + element.month] += element.load)
: (monthData[element.year + '-' + element.month] = element.load)
element.year in yearData
? (yearData[element.year] += element.load)
: (yearData[element.year] = element.load)
})
// Agregation for Month data
const agregatedMonthData = await buildAgregatedData(
monthData,
'com.grandlyon.egl.month'
)
await storeData(agregatedMonthData, 'com.grandlyon.egl.month', [
'year',
'month'
])
// Agregation for Year data
const agregatedYearData = await buildAgregatedData(
yearData,
'com.grandlyon.egl.year'
)
await storeData(agregatedYearData, 'com.grandlyon.egl.year', ['year'])
/**
* Retrieve and remove old data for a specific doctype
* Return an Array of agregated data
*/
async function buildAgregatedData(data, doctype) {
let agregatedData = []
for (let [key, value] of Object.entries(data)) {
const data = await buildDataFromKey(doctype, key, value)
const oldValue = await resetInProgressAggregatedData(data, doctype)
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
data.load += oldValue
agregatedData.push(data)
}
return agregatedData
}
// async function processData(timeStep, response, baseUrl, apiAuthKey) {
// const doctype = rangeDate[timeStep].doctype;
// const loadProfile = await getData(response, baseUrl, apiAuthKey);
// log("info", "Saving data to Cozy");
// if (doctype === rangeDate.day.doctype) {
// await storeData(loadProfile, rangeDate.day.doctype, rangeDate.day.keys);
// } else if (doctype === rangeDate.month.doctype) {
// await resetInProgressAggregatedData(rangeDate.month.doctype);
// const monthlyData = processMonthlyAggregation(loadProfile, rangeDate.month);
// log("info", "Saving monthly data");
// await storeData(monthlyData, rangeDate.month.doctype, rangeDate.month.keys);
// } else if (doctype === rangeDate.year.doctype) {
// await resetInProgressAggregatedData(rangeDate.year.doctype);
// const yearlyData = processYearAggregation(
// loadProfile,
// rangeDate.year.doctype
// );
// log("info", "Saving yearly data");
// await storeData(yearlyData, rangeDate.year.doctype, rangeDate.year.keys);
// } else {
// throw new Error("Unkonw range type: " + doctype);
// }
// }
async function authenticate(login, password, baseUrl, apiAuthKey) {
const authRequest = {
},
form: {
login: login,
pass: password
},
json: true
}
}
async function getData(response, baseUrl, apiAuthKey) {
log('debug', 'Start date : ' + startDate)
log('debug', 'End date : ' + endDate)
method: 'POST',
uri: baseUrl + '/getAllAgregatsByAbonnement.aspx',
},
form: {
token: response.resultatRetour.token,
num_abt: response.resultatRetour.num_abt,
date_debut: startDate,
date_fin: endDate
},
json: true
log('info', 'origin response size is : ' + response.resultatRetour.length)
.filter(value => value.ValeurIndex)
const dataLen = data.length
log('info', 'filtered size is : ' + dataLen)
if (index !== 0 && index < dataLen) {
load: value.ValeurIndex - data[index - 1].ValeurIndex,
year: parseInt(time.format('YYYY')),
month: parseInt(time.format('M')),
day: parseInt(time.format('D')),
hour: 0,
minute: 0,
type: value.TypeAgregat
year: parseInt(time.format('YYYY')),
month: parseInt(time.format('M')),
day: parseInt(time.format('D')),
// function processYearAggregation(data, doctype) {
// log("info", "Start aggregation for : " + doctype);
// const grouped = data.reduce(reduceYearFunction, {});
// return Object.values(grouped);
// }
// function processMonthlyAggregation(data, range) {
// log("info", "Start aggregation for : " + range.doctype);
// // Filter by year
// const tmpData = groupBy(data, "year");
// const keys = Object.keys(tmpData);
// var dataToStore = [];
// // Monthly aggregation
// for (const index in keys) {
// // Get daily data of a year
// var monthlyData = tmpData[keys[index]];
// // Monthly aggregation
// var aggregatedData = monthlyData.reduce(reduceMonthFunction, {});
// // Store it
// dataToStore = dataToStore.concat(Object.values(aggregatedData));
// }
// return dataToStore;
// }
// function groupBy(xs, key) {
// return xs.reduce(function(rv, x) {
// (rv[x[key]] = rv[x[key]] || []).push(x);
// return rv;
// }, {});
// }
// function reduceYearFunction(acc, x) {
// var id = acc[x.year];
// if (id) {
// id.load += x.load;
// } else {
// acc[x.year] = x;
// }
// return acc;
// }
// function reduceMonthFunction(acc, x) {
// var id = acc[x.month];
// if (id) {
// id.load += x.load;
// } else {
// acc[x.month] = x;
// }
// return acc;
// }
/**
* Save data in the right doctype db and prevent duplicated keys
*/
async function storeData(data, doctype, filterKeys) {
log('debug', 'Store into ' + doctype)
log('debug', 'Store into keys : ' + filterKeys)
// data.map(v => {
// log("info", "Saving data " + v.load + " for " + v.day + "/" + v.month + "/" + v.year);
// });
const filteredDocuments = await hydrateAndFilter(data, doctype, {
keys: filterKeys
})
return await addData(filteredDocuments, doctype)
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
/**
* Format an entry for DB storage
* using key and value
* For year doctype: key = "YYYY"
* For month doctype: key = "YYYY-MM"
*/
async function buildDataFromKey(doctype, key, value) {
let year, month, day, hour
if (doctype === 'com.grandlyon.egl.year') {
year = key
month = 1
day = 0
hour = 0
} else if (doctype === 'com.grandlyon.egl.month') {
const split = key.split('-')
year = split[0]
month = split[1]
day = 0
hour = 0
} else {
const split = key.split('-')
year = split[0]
month = split[1]
day = split[2]
hour = split[3]
}
return {
load: Math.round(value * 10000) / 10000,
year: parseInt(year),
month: parseInt(month),
day: parseInt(day),
hour: parseInt(hour),
minute: 0
}
}
/**
* Function handling special case.
* The temporary aggregated data need to be remove in order for the most recent one te be saved.
* { load: 76.712, month: 2020, ... } need to be replace by
// /!\ Warning: cannot use mongo queries because not supported for dev by cozy-konnectors-libs
log('debug', 'Remove aggregated data for ' + doctype)
const result = await cozyClient.data.findAll(doctype)
if (result && result.length > 0) {
// Yearly case
filtered = result.filter(function(el) {
return el.year == data.year
})
} else if (doctype === 'com.grandlyon.egl.month') {
filtered = result.filter(function(el) {
return el.year == data.year && el.month == data.month
})
} else {
// Hourly case
filtered = result.filter(function(el) {
return (
el.year == data.year &&
el.month == data.month &&
el.day == data.day &&
el.hour == data.hour
)
})
sum += doc.load
log('debug', 'Removing this entry for ' + doc.load)
await cozyClient.data.delete(doctype, doc)