Issues (1577)

myems-api/reports/meterenergy.py (2 issues)

Severity
1
import re
2
from datetime import datetime, timedelta, timezone
3
from decimal import Decimal
4
import falcon
5
import mysql.connector
6
import simplejson as json
7
import config
8
import excelexporters.meterenergy
9
from core import utilities
10
from core.useractivity import access_control, api_key_control
11
12
13
class Reporting:
14
    def __init__(self):
15
        """"Initializes Reporting"""
16
        pass
17
18
    @staticmethod
19
    def on_options(req, resp):
20
        _ = req
21
        resp.status = falcon.HTTP_200
22
23
    ####################################################################################################################
24
    # PROCEDURES
25
    # Step 1: valid parameters
26
    # Step 2: query the meter and energy category
27
    # Step 3: query associated points
28
    # Step 4: query base period energy consumption
29
    # Step 5: query reporting period energy consumption
30
    # Step 6: query tariff data
31
    # Step 7: query associated points data
32
    # Step 8: construct the report
33
    ####################################################################################################################
34
    @staticmethod
35
    def on_get(req, resp):
36
        if 'API-KEY' not in req.headers or \
37
                not isinstance(req.headers['API-KEY'], str) or \
38
                len(str.strip(req.headers['API-KEY'])) == 0:
39
            access_control(req)
40
        else:
41
            api_key_control(req)
42
        print(req.params)
43
        # this procedure accepts meter id or meter uuid to identify a meter
44
        meter_id = req.params.get('meterid')
45
        meter_uuid = req.params.get('meteruuid')
46
        period_type = req.params.get('periodtype')
47
        base_period_start_datetime_local = req.params.get('baseperiodstartdatetime')
48
        base_period_end_datetime_local = req.params.get('baseperiodenddatetime')
49
        reporting_period_start_datetime_local = req.params.get('reportingperiodstartdatetime')
50
        reporting_period_end_datetime_local = req.params.get('reportingperiodenddatetime')
51
        language = req.params.get('language')
52
        quick_mode = req.params.get('quickmode')
53
54
        ################################################################################################################
55
        # Step 1: valid parameters
56
        ################################################################################################################
57
        if meter_id is None and meter_uuid is None:
58
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST', description='API.INVALID_METER_ID')
59
60
        if meter_id is not None:
61
            meter_id = str.strip(meter_id)
62
            if not meter_id.isdigit() or int(meter_id) <= 0:
63
                raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
64
                                       description='API.INVALID_METER_ID')
65
66
        if meter_uuid is not None:
67
            regex = re.compile(r'^[a-f0-9]{8}-?[a-f0-9]{4}-?4[a-f0-9]{3}-?[89ab][a-f0-9]{3}-?[a-f0-9]{12}\Z', re.I)
68
            match = regex.match(str.strip(meter_uuid))
69
            if not bool(match):
70
                raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
71
                                       description='API.INVALID_METER_UUID')
72
73
        if period_type is None:
74
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
75
                                   description='API.INVALID_PERIOD_TYPE')
76
        else:
77
            period_type = str.strip(period_type)
78
            if period_type not in ['hourly', 'daily', 'weekly', 'monthly', 'yearly']:
79
                raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
80
                                       description='API.INVALID_PERIOD_TYPE')
81
82
        timezone_offset = int(config.utc_offset[1:3]) * 60 + int(config.utc_offset[4:6])
83
        if config.utc_offset[0] == '-':
84
            timezone_offset = -timezone_offset
85
86
        base_start_datetime_utc = None
87
        if base_period_start_datetime_local is not None and len(str.strip(base_period_start_datetime_local)) > 0:
88
            base_period_start_datetime_local = str.strip(base_period_start_datetime_local)
89
            try:
90
                base_start_datetime_utc = datetime.strptime(base_period_start_datetime_local, '%Y-%m-%dT%H:%M:%S')
91
            except ValueError:
92
                raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
93
                                       description="API.INVALID_BASE_PERIOD_START_DATETIME")
94
            base_start_datetime_utc = \
95
                base_start_datetime_utc.replace(tzinfo=timezone.utc) - timedelta(minutes=timezone_offset)
96
            # nomalize the start datetime
97
            if config.minutes_to_count == 30 and base_start_datetime_utc.minute >= 30:
98
                base_start_datetime_utc = base_start_datetime_utc.replace(minute=30, second=0, microsecond=0)
99
            else:
100
                base_start_datetime_utc = base_start_datetime_utc.replace(minute=0, second=0, microsecond=0)
101
102
        base_end_datetime_utc = None
103
        if base_period_end_datetime_local is not None and len(str.strip(base_period_end_datetime_local)) > 0:
104
            base_period_end_datetime_local = str.strip(base_period_end_datetime_local)
105
            try:
106
                base_end_datetime_utc = datetime.strptime(base_period_end_datetime_local, '%Y-%m-%dT%H:%M:%S')
107
            except ValueError:
108
                raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
109
                                       description="API.INVALID_BASE_PERIOD_END_DATETIME")
110
            base_end_datetime_utc = \
111
                base_end_datetime_utc.replace(tzinfo=timezone.utc) - timedelta(minutes=timezone_offset)
112
113
        if base_start_datetime_utc is not None and base_end_datetime_utc is not None and \
114
                base_start_datetime_utc >= base_end_datetime_utc:
115
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
116
                                   description='API.INVALID_BASE_PERIOD_END_DATETIME')
117
118
        if reporting_period_start_datetime_local is None:
119
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
120
                                   description="API.INVALID_REPORTING_PERIOD_START_DATETIME")
121
        else:
122
            reporting_period_start_datetime_local = str.strip(reporting_period_start_datetime_local)
123
            try:
124
                reporting_start_datetime_utc = datetime.strptime(reporting_period_start_datetime_local,
125
                                                                 '%Y-%m-%dT%H:%M:%S')
126
            except ValueError:
127
                raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
128
                                       description="API.INVALID_REPORTING_PERIOD_START_DATETIME")
129
            reporting_start_datetime_utc = \
130
                reporting_start_datetime_utc.replace(tzinfo=timezone.utc) - timedelta(minutes=timezone_offset)
131
            # nomalize the start datetime
132
            if config.minutes_to_count == 30 and reporting_start_datetime_utc.minute >= 30:
133
                reporting_start_datetime_utc = reporting_start_datetime_utc.replace(minute=30, second=0, microsecond=0)
134
            else:
135
                reporting_start_datetime_utc = reporting_start_datetime_utc.replace(minute=0, second=0, microsecond=0)
136
137
        if reporting_period_end_datetime_local is None:
138
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
139
                                   description="API.INVALID_REPORTING_PERIOD_END_DATETIME")
140
        else:
141
            reporting_period_end_datetime_local = str.strip(reporting_period_end_datetime_local)
142
            try:
143
                reporting_end_datetime_utc = datetime.strptime(reporting_period_end_datetime_local,
144
                                                               '%Y-%m-%dT%H:%M:%S')
145
            except ValueError:
146
                raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
147
                                       description="API.INVALID_REPORTING_PERIOD_END_DATETIME")
148
            reporting_end_datetime_utc = reporting_end_datetime_utc.replace(tzinfo=timezone.utc) - \
149
                timedelta(minutes=timezone_offset)
150
151
        if reporting_start_datetime_utc >= reporting_end_datetime_utc:
152
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
153
                                   description='API.INVALID_REPORTING_PERIOD_END_DATETIME')
154
155
        # if turn quick mode on, do not return parameters data and excel file
156
        is_quick_mode = False
157
        if quick_mode is not None and \
158
                len(str.strip(quick_mode)) > 0 and \
159
                str.lower(str.strip(quick_mode)) in ('true', 't', 'on', 'yes', 'y'):
160
            is_quick_mode = True
161
162
        trans = utilities.get_translation(language)
163
        trans.install()
164
        _ = trans.gettext
165
166
        ################################################################################################################
167
        # Step 2: query the meter and energy category
168
        ################################################################################################################
169
        cnx_system = mysql.connector.connect(**config.myems_system_db)
170
        cursor_system = cnx_system.cursor()
171
172
        cnx_energy = mysql.connector.connect(**config.myems_energy_db)
173
        cursor_energy = cnx_energy.cursor()
174
175
        cnx_historical = mysql.connector.connect(**config.myems_historical_db)
176
        cursor_historical = cnx_historical.cursor()
177
178
        if meter_id is not None:
179
            cursor_system.execute(" SELECT m.id, m.name, m.cost_center_id, m.energy_category_id, "
180
                                  "        ec.name, ec.unit_of_measure, ec.kgce, ec.kgco2e "
181
                                  " FROM tbl_meters m, tbl_energy_categories ec "
182
                                  " WHERE m.id = %s AND m.energy_category_id = ec.id ", (meter_id,))
183
            row_meter = cursor_system.fetchone()
184
        elif meter_uuid is not None:
185
            cursor_system.execute(" SELECT m.id, m.name, m.cost_center_id, m.energy_category_id, "
186
                                  "        ec.name, ec.unit_of_measure, ec.kgce, ec.kgco2e "
187
                                  " FROM tbl_meters m, tbl_energy_categories ec "
188
                                  " WHERE m.uuid = %s AND m.energy_category_id = ec.id ", (meter_uuid,))
189
            row_meter = cursor_system.fetchone()
190
191
        if row_meter is None:
0 ignored issues
show
The variable row_meter does not seem to be defined for all execution paths.
Loading history...
192
            if cursor_system:
193
                cursor_system.close()
194
            if cnx_system:
195
                cnx_system.close()
196
197
            if cursor_energy:
198
                cursor_energy.close()
199
            if cnx_energy:
200
                cnx_energy.close()
201
202
            if cursor_historical:
203
                cursor_historical.close()
204
            if cnx_historical:
205
                cnx_historical.close()
206
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND', description='API.METER_NOT_FOUND')
207
208
        meter = dict()
209
        meter['id'] = row_meter[0]
210
        meter['name'] = row_meter[1]
211
        meter['cost_center_id'] = row_meter[2]
212
        meter['energy_category_id'] = row_meter[3]
213
        meter['energy_category_name'] = row_meter[4]
214
        meter['unit_of_measure'] = row_meter[5]
215
        meter['kgce'] = row_meter[6]
216
        meter['kgco2e'] = row_meter[7]
217
218
        ################################################################################################################
219
        # Step 3: query associated points
220
        ################################################################################################################
221
        point_list = list()
222
        cursor_system.execute(" SELECT p.id, p.name, p.units, p.object_type  "
223
                              " FROM tbl_meters m, tbl_meters_points mp, tbl_points p "
224
                              " WHERE m.id = %s AND m.id = mp.meter_id AND mp.point_id = p.id "
225
                              " ORDER BY p.id ", (meter['id'],))
226
        rows_points = cursor_system.fetchall()
227
        if rows_points is not None and len(rows_points) > 0:
228
            for row in rows_points:
229
                point_list.append({"id": row[0], "name": row[1], "units": row[2], "object_type": row[3]})
230
231
        ################################################################################################################
232
        # Step 4: query base period energy consumption
233
        ################################################################################################################
234
        cnx_energy = mysql.connector.connect(**config.myems_energy_db)
235
        cursor_energy = cnx_energy.cursor()
236
        query = (" SELECT start_datetime_utc, actual_value "
237
                 " FROM tbl_meter_hourly "
238
                 " WHERE meter_id = %s "
239
                 " AND start_datetime_utc >= %s "
240
                 " AND start_datetime_utc < %s "
241
                 " ORDER BY start_datetime_utc ")
242
        cursor_energy.execute(query, (meter['id'], base_start_datetime_utc, base_end_datetime_utc))
243
        rows_meter_hourly = cursor_energy.fetchall()
244
245
        rows_meter_periodically = utilities.aggregate_hourly_data_by_period(rows_meter_hourly,
246
                                                                            base_start_datetime_utc,
247
                                                                            base_end_datetime_utc,
248
                                                                            period_type)
249
        base = dict()
250
        base['timestamps'] = list()
251
        base['values'] = list()
252
        base['total_in_category'] = Decimal(0.0)
253
        base['total_in_kgce'] = Decimal(0.0)
254
        base['total_in_kgco2e'] = Decimal(0.0)
255
256
        for row_meter_periodically in rows_meter_periodically:
257
            current_datetime_local = row_meter_periodically[0].replace(tzinfo=timezone.utc) + \
258
                                     timedelta(minutes=timezone_offset)
259
            if period_type == 'hourly':
260
                current_datetime = current_datetime_local.isoformat()[0:19]
261
            elif period_type == 'daily':
262
                current_datetime = current_datetime_local.isoformat()[0:10]
263
            elif period_type == 'weekly':
264
                current_datetime = current_datetime_local.isoformat()[0:10]
265
            elif period_type == 'monthly':
266
                current_datetime = current_datetime_local.isoformat()[0:7]
267
            elif period_type == 'yearly':
268
                current_datetime = current_datetime_local.isoformat()[0:4]
269
270
            actual_value = Decimal(0.0) if row_meter_periodically[1] is None else row_meter_periodically[1]
271
            base['timestamps'].append(current_datetime)
0 ignored issues
show
The variable current_datetime does not seem to be defined for all execution paths.
Loading history...
272
            base['values'].append(actual_value)
273
            base['total_in_category'] += actual_value
274
            base['total_in_kgce'] += actual_value * meter['kgce']
275
            base['total_in_kgco2e'] += actual_value * meter['kgco2e']
276
277
        ################################################################################################################
278
        # Step 5: query reporting period energy consumption
279
        ################################################################################################################
280
        query = (" SELECT start_datetime_utc, actual_value "
281
                 " FROM tbl_meter_hourly "
282
                 " WHERE meter_id = %s "
283
                 " AND start_datetime_utc >= %s "
284
                 " AND start_datetime_utc < %s "
285
                 " ORDER BY start_datetime_utc ")
286
        cursor_energy.execute(query, (meter['id'], reporting_start_datetime_utc, reporting_end_datetime_utc))
287
        rows_meter_hourly = cursor_energy.fetchall()
288
289
        rows_meter_periodically = utilities.aggregate_hourly_data_by_period(rows_meter_hourly,
290
                                                                            reporting_start_datetime_utc,
291
                                                                            reporting_end_datetime_utc,
292
                                                                            period_type)
293
        reporting = dict()
294
        reporting['timestamps'] = list()
295
        reporting['values'] = list()
296
        reporting['rates'] = list()
297
        reporting['total_in_category'] = Decimal(0.0)
298
        reporting['total_in_kgce'] = Decimal(0.0)
299
        reporting['total_in_kgco2e'] = Decimal(0.0)
300
        reporting['toppeak'] = Decimal(0.0)
301
        reporting['onpeak'] = Decimal(0.0)
302
        reporting['midpeak'] = Decimal(0.0)
303
        reporting['offpeak'] = Decimal(0.0)
304
        reporting['deep'] = Decimal(0.0)
305
306
        for row_meter_periodically in rows_meter_periodically:
307
            current_datetime_local = row_meter_periodically[0].replace(tzinfo=timezone.utc) + \
308
                                     timedelta(minutes=timezone_offset)
309
            if period_type == 'hourly':
310
                current_datetime = current_datetime_local.isoformat()[0:19]
311
            elif period_type == 'daily':
312
                current_datetime = current_datetime_local.isoformat()[0:10]
313
            elif period_type == 'weekly':
314
                current_datetime = current_datetime_local.isoformat()[0:10]
315
            elif period_type == 'monthly':
316
                current_datetime = current_datetime_local.isoformat()[0:7]
317
            elif period_type == 'yearly':
318
                current_datetime = current_datetime_local.isoformat()[0:4]
319
320
            actual_value = Decimal(0.0) if row_meter_periodically[1] is None else row_meter_periodically[1]
321
322
            reporting['timestamps'].append(current_datetime)
323
            reporting['values'].append(actual_value)
324
            reporting['total_in_category'] += actual_value
325
            reporting['total_in_kgce'] += actual_value * meter['kgce']
326
            reporting['total_in_kgco2e'] += actual_value * meter['kgco2e']
327
328
        for index, value in enumerate(reporting['values']):
329
            if index < len(base['values']) and base['values'][index] != 0 and value != 0:
330
                reporting['rates'].append((value - base['values'][index]) / base['values'][index])
331
            else:
332
                reporting['rates'].append(None)
333
334
        energy_category_tariff_dict = utilities.get_energy_category_peak_types(meter['cost_center_id'],
335
                                                                               meter['energy_category_id'],
336
                                                                               reporting_start_datetime_utc,
337
                                                                               reporting_end_datetime_utc)
338
        for row_meter_hourly in rows_meter_hourly:
339
            peak_type = energy_category_tariff_dict.get(row_meter_hourly[0], None)
340
            if peak_type == 'toppeak':
341
                reporting['toppeak'] += row_meter_hourly[1]
342
            elif peak_type == 'onpeak':
343
                reporting['onpeak'] += row_meter_hourly[1]
344
            elif peak_type == 'midpeak':
345
                reporting['midpeak'] += row_meter_hourly[1]
346
            elif peak_type == 'offpeak':
347
                reporting['offpeak'] += row_meter_hourly[1]
348
            elif peak_type == 'deep':
349
                reporting['deep'] += row_meter_hourly[1]
350
        ################################################################################################################
351
        # Step 6: query tariff data
352
        ################################################################################################################
353
        parameters_data = dict()
354
        parameters_data['names'] = list()
355
        parameters_data['timestamps'] = list()
356
        parameters_data['values'] = list()
357
358
        if config.is_tariff_appended and not is_quick_mode:
359
            tariff_dict = utilities.get_energy_category_tariffs(meter['cost_center_id'],
360
                                                                meter['energy_category_id'],
361
                                                                reporting_start_datetime_utc,
362
                                                                reporting_end_datetime_utc)
363
            tariff_timestamp_list = list()
364
            tariff_value_list = list()
365
            for k, v in tariff_dict.items():
366
                # convert k from utc to local
367
                k = k + timedelta(minutes=timezone_offset)
368
                tariff_timestamp_list.append(k.isoformat()[0:19])
369
                tariff_value_list.append(v)
370
371
            parameters_data['names'].append(_('Tariff') + '-' + meter['energy_category_name'])
372
            parameters_data['timestamps'].append(tariff_timestamp_list)
373
            parameters_data['values'].append(tariff_value_list)
374
375
        ################################################################################################################
376
        # Step 7: query associated points data
377
        ################################################################################################################
378
        if not is_quick_mode:
379
            for point in point_list:
380
                point_values = []
381
                point_timestamps = []
382
                if point['object_type'] == 'ENERGY_VALUE':
383
                    query = (" SELECT utc_date_time, actual_value "
384
                             " FROM tbl_energy_value "
385
                             " WHERE point_id = %s "
386
                             "       AND utc_date_time BETWEEN %s AND %s "
387
                             " ORDER BY utc_date_time ")
388
                    cursor_historical.execute(query, (point['id'],
389
                                                      reporting_start_datetime_utc,
390
                                                      reporting_end_datetime_utc))
391
                    rows = cursor_historical.fetchall()
392
393
                    if rows is not None and len(rows) > 0:
394
                        for row in rows:
395
                            current_datetime_local = row[0].replace(tzinfo=timezone.utc) + \
396
                                                     timedelta(minutes=timezone_offset)
397
                            current_datetime = current_datetime_local.isoformat()[0:19]
398
                            point_timestamps.append(current_datetime)
399
                            point_values.append(row[1])
400
                elif point['object_type'] == 'ANALOG_VALUE':
401
                    query = (" SELECT utc_date_time, actual_value "
402
                             " FROM tbl_analog_value "
403
                             " WHERE point_id = %s "
404
                             "       AND utc_date_time BETWEEN %s AND %s "
405
                             " ORDER BY utc_date_time ")
406
                    cursor_historical.execute(query, (point['id'],
407
                                                      reporting_start_datetime_utc,
408
                                                      reporting_end_datetime_utc))
409
                    rows = cursor_historical.fetchall()
410
411
                    if rows is not None and len(rows) > 0:
412
                        for row in rows:
413
                            current_datetime_local = row[0].replace(tzinfo=timezone.utc) + \
414
                                                     timedelta(minutes=timezone_offset)
415
                            current_datetime = current_datetime_local.isoformat()[0:19]
416
                            point_timestamps.append(current_datetime)
417
                            point_values.append(row[1])
418
                elif point['object_type'] == 'DIGITAL_VALUE':
419
                    query = (" SELECT utc_date_time, actual_value "
420
                             " FROM tbl_digital_value "
421
                             " WHERE point_id = %s "
422
                             "       AND utc_date_time BETWEEN %s AND %s "
423
                             " ORDER BY utc_date_time ")
424
                    cursor_historical.execute(query, (point['id'],
425
                                                      reporting_start_datetime_utc,
426
                                                      reporting_end_datetime_utc))
427
                    rows = cursor_historical.fetchall()
428
429
                    if rows is not None and len(rows) > 0:
430
                        for row in rows:
431
                            current_datetime_local = row[0].replace(tzinfo=timezone.utc) + \
432
                                                     timedelta(minutes=timezone_offset)
433
                            current_datetime = current_datetime_local.isoformat()[0:19]
434
                            point_timestamps.append(current_datetime)
435
                            point_values.append(row[1])
436
437
                parameters_data['names'].append(point['name'] + ' (' + point['units'] + ')')
438
                parameters_data['timestamps'].append(point_timestamps)
439
                parameters_data['values'].append(point_values)
440
441
        ################################################################################################################
442
        # Step 8: construct the report
443
        ################################################################################################################
444
        if cursor_system:
445
            cursor_system.close()
446
        if cnx_system:
447
            cnx_system.close()
448
449
        if cursor_energy:
450
            cursor_energy.close()
451
        if cnx_energy:
452
            cnx_energy.close()
453
454
        if cursor_historical:
455
            cursor_historical.close()
456
        if cnx_historical:
457
            cnx_historical.close()
458
        result = {
459
            "meter": {
460
                "cost_center_id": meter['cost_center_id'],
461
                "energy_category_id": meter['energy_category_id'],
462
                "energy_category_name": meter['energy_category_name'],
463
                "unit_of_measure": meter['unit_of_measure'],
464
                "kgce": meter['kgce'],
465
                "kgco2e": meter['kgco2e'],
466
                "name": meter['name'],
467
                "id": meter['id'],
468
            },
469
            "base_period": {
470
                "total_in_category": base['total_in_category'],
471
                "total_in_kgce": base['total_in_kgce'],
472
                "total_in_kgco2e": base['total_in_kgco2e'],
473
                "timestamps": base['timestamps'],
474
                "values": base['values']
475
            },
476
            "reporting_period": {
477
                "increment_rate":
478
                    (reporting['total_in_category'] - base['total_in_category']) / base['total_in_category']
479
                    if base['total_in_category'] != Decimal(0.0) else None,
480
                "total_in_category": reporting['total_in_category'],
481
                "total_in_kgce": reporting['total_in_kgce'],
482
                "total_in_kgco2e": reporting['total_in_kgco2e'],
483
                "toppeak": reporting['toppeak'],
484
                "onpeak": reporting['onpeak'],
485
                "midpeak": reporting['midpeak'],
486
                "offpeak": reporting['offpeak'],
487
                "deep": reporting['deep'],
488
                "timestamps": reporting['timestamps'],
489
                "values": reporting['values'],
490
                "rates": reporting['rates'],
491
            },
492
            "parameters": {
493
                "names": parameters_data['names'],
494
                "timestamps": parameters_data['timestamps'],
495
                "values": parameters_data['values']
496
            },
497
        }
498
        # export result to Excel file and then encode the file to base64 string
499
        if not is_quick_mode:
500
            result['excel_bytes_base64'] = \
501
                excelexporters.meterenergy.export(result,
502
                                                  meter['name'],
503
                                                  reporting_period_start_datetime_local,
504
                                                  reporting_period_end_datetime_local,
505
                                                  base_period_start_datetime_local,
506
                                                  base_period_end_datetime_local,
507
                                                  period_type,
508
                                                  language)
509
510
        resp.text = json.dumps(result)
511