Newer
Older
} = require('cozy-konnector-libs')
const moment = require('moment')
const rp = require('request-promise')
moment.locale('fr') // set the language
moment.tz.setDefault('Europe/Paris') // set the timezone
/*** Connector Constants ***/
.format('YYYY-MM-DD')
const endDate = moment().format('YYYY-MM-DD')
const baseUrl = 'https://gw.hml.api.enedis.fr'
// 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) {
try {
const { access_token } = fields
const fetchedData = await getDailyData(access_token, usage_point_id)
log('info', 'Process data')
await processData(fetchedData)
log('info', 'Saving data to Cozy')
} catch (err) {
log('error', err.message)
}
// Retrieve data from the API
// Format: { value: "Wh", "date": "YYYY-MM-DD" }
async function getDailyData(token, usagePointID) {
const dataRequest = {
method: 'GET',
uri:
baseUrl +
startDate +
'&end=' +
endDate +
'&usage_point_id=' +
usagePointID,
headers: {
Accept: 'application/json',
Authorization: 'Bearer ' + token
}
}
try {
const response = await rp(dataRequest)
return response
} catch (error) {
throw error
}
}
async function processData(data) {
const parsedData = JSON.parse(data)
const intervalData = parsedData.meter_reading.interval_reading
const formatedData = await formateData(intervalData)
// Remove data for existing days into the DB
const filteredData = await hydrateAndFilter(formatedData, 'io.enedis.day', {
keys: ['year', 'month', 'day']
75
76
77
78
79
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
// Store new day data
await storeData(filteredData, 'io.enedis.day', ['year', 'month', 'day'])
// Sum year and month values into object with year or year-month as keys
if (filteredData && filteredData.length > 0) {
let yearData = {}
let monthData = {}
filteredData.forEach(element => {
element.year in yearData
? (yearData[element.year] += element.load)
: (yearData[element.year] = element.load)
element.year + '-' + element.month in monthData
? (monthData[element.year + '-' + element.month] += element.load)
: (monthData[element.year + '-' + element.month] = element.load)
})
const agregatedYearData = await agregateData('io.enedis.year', yearData)
await storeData(agregatedYearData, 'io.enedis.year', ['year'])
const agregatedMonthData = await agregateData('io.enedis.month', monthData)
await storeData(agregatedMonthData, 'io.enedis.month', ['year', 'month'])
}
}
/**
* Save data in the right doctype db and prevent duplicated keys
*/
async function storeData(data, doctype, filterKeys) {
log('debug', doctype, 'Store into')
const filteredDocuments = await hydrateAndFilter(data, doctype, {
keys: filterKeys
})
return await addData(filteredDocuments, doctype)
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
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
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
/**
* Format data for DB storage
* Remove bad data
*/
async function formateData(data) {
log('info', 'Formating data')
log('debug', start, 'Start date')
return data.map(record => {
const date = moment(record.date, 'YYYY/MM/DD')
if (record.value != -2) {
return {
load: parseFloat(record.value / 1000),
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'))
}
}
})
}
/**
* Retrieve and remove old data for a specific doctype
* Return an Array of agregated data
*/
async function agregateData(doctype, data) {
let agregatedData = []
for (let [key, value] of Object.entries(data)) {
const data = await buildDataFromKey(doctype, key, value)
const oldValue = await resetInProgressAggregatedData(doctype, data)
data.load += oldValue
agregatedData.push(data)
}
return agregatedData
}
/**
* 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
if (doctype === 'io.enedis.year') {
year = key
month = 1
} else {
const split = key.split('-')
year = split[0]
month = split[1]
}
return {
load: Math.round(value * 1000) / 1000,
year: parseInt(year),
month: parseInt(month),
day: 0,
hour: 0,
minute: 0
}
}
/**
* Function handling special case.
* The temporary aggregated data need to be remove in order for the most recent one te be saved.
* ex for io.enedis.year :
* { load: 76.712, year: 2020, ... } need to be replace by
* { load: 82.212, year: 2020, ... } after enedis data reprocess
*/
async function resetInProgressAggregatedData(doctype, data) {
// /!\ Warning: cannot use mongo queries because not supported for dev by cozy-konnectors-libs
log('debug', doctype, 'Remove aggregated data for')
const result = await cozyClient.data.findAll(doctype)
if (result && result.length > 0) {
// Filter data to remove
var filtered = []
if (doctype === 'io.enedis.year') {
// Yearly case
filtered = result.filter(function(el) {
return el.year == data.year
})
} else {
// Monthly case
filtered = result.filter(function(el) {
return el.year == data.year && el.month == data.month
})
}
// Remove data
let sum = 0.0
for (const doc of filtered) {
sum += doc.load
log('debug', doc, 'Removing this entry for ' + doctype)
await cozyClient.data.delete(doctype, doc)
}
return sum
}
return 0.0