Passed
Push — master ( 283033...66ce56 )
by Guangyu
07:51 queued 11s
created

myems-api/reports/equipmentefficiency.py (1 issue)

1
import falcon
2
import simplejson as json
3
import mysql.connector
4
import config
5
from datetime import datetime, timedelta, timezone
6
from core import utilities
7
from decimal import Decimal
8
import excelexporters.equipmentefficiency
9
10
11
class Reporting:
12
    @staticmethod
13
    def __init__():
14
        """"Initializes Reporting"""
15
        pass
16
17
    @staticmethod
18
    def on_options(req, resp):
19
        resp.status = falcon.HTTP_200
20
21
    ####################################################################################################################
22
    # PROCEDURES
23
    # Step 1: valid parameters
24
    # Step 2: query the equipment
25
    # Step 3: query associated points
26
    # Step 4: query associated fractions
27
    # Step 5: query fractions' numerator and denominator
28
    # Step 6: calculate base period fractions
29
    # Step 7: calculate reporting period fractions
30
    # Step 8: query associated points data
31
    # Step 9: construct the report
32
    ####################################################################################################################
33
    @staticmethod
34
    def on_get(req, resp):
35
        print(req.params)
36
        equipment_id = req.params.get('equipmentid')
37
        period_type = req.params.get('periodtype')
38
        base_start_datetime_local = req.params.get('baseperiodstartdatetime')
39
        base_end_datetime_local = req.params.get('baseperiodenddatetime')
40
        reporting_start_datetime_local = req.params.get('reportingperiodstartdatetime')
41
        reporting_end_datetime_local = req.params.get('reportingperiodenddatetime')
42
43
        ################################################################################################################
44
        # Step 1: valid parameters
45
        ################################################################################################################
46
        if equipment_id is None:
47
            raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST', description='API.INVALID_EQUIPMENT_ID')
48
        else:
49
            equipment_id = str.strip(equipment_id)
50
            if not equipment_id.isdigit() or int(equipment_id) <= 0:
51
                raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST', description='API.INVALID_EQUIPMENT_ID')
52
53
        if period_type is None:
54
            raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST', description='API.INVALID_PERIOD_TYPE')
55
        else:
56
            period_type = str.strip(period_type)
57
            if period_type not in ['hourly', 'daily', 'weekly', 'monthly', 'yearly']:
58
                raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST', description='API.INVALID_PERIOD_TYPE')
59
60
        timezone_offset = int(config.utc_offset[1:3]) * 60 + int(config.utc_offset[4:6])
61
        if config.utc_offset[0] == '-':
62
            timezone_offset = -timezone_offset
63
64
        base_start_datetime_utc = None
65
        if base_start_datetime_local is not None and len(str.strip(base_start_datetime_local)) > 0:
66
            base_start_datetime_local = str.strip(base_start_datetime_local)
67
            try:
68
                base_start_datetime_utc = datetime.strptime(base_start_datetime_local,
69
                                                            '%Y-%m-%dT%H:%M:%S').replace(tzinfo=timezone.utc) - \
70
                    timedelta(minutes=timezone_offset)
71
            except ValueError:
72
                raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST',
73
                                       description="API.INVALID_BASE_PERIOD_START_DATETIME")
74
75
        base_end_datetime_utc = None
76
        if base_end_datetime_local is not None and len(str.strip(base_end_datetime_local)) > 0:
77
            base_end_datetime_local = str.strip(base_end_datetime_local)
78
            try:
79
                base_end_datetime_utc = datetime.strptime(base_end_datetime_local,
80
                                                          '%Y-%m-%dT%H:%M:%S').replace(tzinfo=timezone.utc) - \
81
                    timedelta(minutes=timezone_offset)
82
            except ValueError:
83
                raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST',
84
                                       description="API.INVALID_BASE_PERIOD_END_DATETIME")
85
86
        if base_start_datetime_utc is not None and base_end_datetime_utc is not None and \
87
                base_start_datetime_utc >= base_end_datetime_utc:
88
            raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST',
89
                                   description='API.INVALID_BASE_PERIOD_END_DATETIME')
90
91
        if reporting_start_datetime_local is None:
92
            raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST',
93
                                   description="API.INVALID_REPORTING_PERIOD_START_DATETIME")
94
        else:
95
            reporting_start_datetime_local = str.strip(reporting_start_datetime_local)
96
            try:
97
                reporting_start_datetime_utc = datetime.strptime(reporting_start_datetime_local,
98
                                                                 '%Y-%m-%dT%H:%M:%S').replace(tzinfo=timezone.utc) - \
99
                    timedelta(minutes=timezone_offset)
100
            except ValueError:
101
                raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST',
102
                                       description="API.INVALID_REPORTING_PERIOD_START_DATETIME")
103
104
        if reporting_end_datetime_local is None:
105
            raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST',
106
                                   description="API.INVALID_REPORTING_PERIOD_END_DATETIME")
107
        else:
108
            reporting_end_datetime_local = str.strip(reporting_end_datetime_local)
109
            try:
110
                reporting_end_datetime_utc = datetime.strptime(reporting_end_datetime_local,
111
                                                               '%Y-%m-%dT%H:%M:%S').replace(tzinfo=timezone.utc) - \
112
                    timedelta(minutes=timezone_offset)
113
            except ValueError:
114
                raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST',
115
                                       description="API.INVALID_REPORTING_PERIOD_END_DATETIME")
116
117
        if reporting_start_datetime_utc >= reporting_end_datetime_utc:
118
            raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST',
119
                                   description='API.INVALID_REPORTING_PERIOD_END_DATETIME')
120
121
        ################################################################################################################
122
        # Step 2: query the equipment
123
        ################################################################################################################
124
        cnx_system = mysql.connector.connect(**config.myems_system_db)
125
        cursor_system = cnx_system.cursor()
126
127
        cnx_energy = mysql.connector.connect(**config.myems_energy_db)
128
        cursor_energy = cnx_energy.cursor()
129
130
        cnx_historical = mysql.connector.connect(**config.myems_historical_db)
131
        cursor_historical = cnx_historical.cursor()
132
133
        cursor_system.execute(" SELECT id, name, cost_center_id "
134
                              " FROM tbl_equipments "
135
                              " WHERE id = %s ", (equipment_id,))
136
        row_equipment = cursor_system.fetchone()
137 View Code Duplication
        if row_equipment is None:
138
            if cursor_system:
139
                cursor_system.close()
140
            if cnx_system:
141
                cnx_system.disconnect()
142
143
            if cursor_energy:
144
                cursor_energy.close()
145
            if cnx_energy:
146
                cnx_energy.disconnect()
147
148
            if cursor_historical:
149
                cursor_historical.close()
150
            if cnx_historical:
151
                cnx_historical.disconnect()
152
            raise falcon.HTTPError(falcon.HTTP_404, title='API.NOT_FOUND', description='API.EQUIPMENT_NOT_FOUND')
153
154
        equipment = dict()
155
        equipment['id'] = row_equipment[0]
156
        equipment['name'] = row_equipment[1]
157
        equipment['cost_center_id'] = row_equipment[2]
158
159
        ################################################################################################################
160
        # Step 3: query associated points
161
        ################################################################################################################
162
        point_list = list()
163
        cursor_system.execute(" SELECT p.id, ep.name, p.units, p.object_type  "
164
                              " FROM tbl_equipments e, tbl_equipments_parameters ep, tbl_points p "
165
                              " WHERE e.id = %s AND e.id = ep.equipment_id AND ep.parameter_type = 'point' "
166
                              "       AND ep.point_id = p.id "
167
                              " ORDER BY p.id ", (equipment['id'],))
168
        rows_points = cursor_system.fetchall()
169
        if rows_points is not None and len(rows_points) > 0:
170
            for row in rows_points:
171
                point_list.append({"id": row[0], "name": row[1], "units": row[2], "object_type": row[3]})
172
173
        print(point_list)
174
        ################################################################################################################
175
        # Step 4: query associated fractions
176
        ################################################################################################################
177
        fraction_list = list()
178
        cursor_system.execute(" SELECT id, name, numerator_meter_uuid, denominator_meter_uuid  "
179
                              " FROM tbl_equipments_parameters "
180
                              " WHERE equipment_id = %s AND parameter_type = 'fraction' ",
181
                              (equipment['id'],))
182
        rows_fractions = cursor_system.fetchall()
183
        if rows_fractions is not None and len(rows_fractions) > 0:
184
            for row in rows_fractions:
185
                fraction_list.append({"id": row[0],
186
                                      "name": row[1],
187
                                      "numerator_meter_uuid": row[2],
188
                                      "denominator_meter_uuid": row[3],
189
                                      })
190
191
        print(fraction_list)
192
193
        ################################################################################################################
194
        # Step 5: query fractions' numerator and denominator
195
        ################################################################################################################
196
        # get all meters
197
        meter_dict = dict()
198
        query = (" SELECT m.id, m.uuid, ec.unit_of_measure "
199
                 " FROM tbl_meters m, tbl_energy_categories ec "
200
                 " WHERE m.energy_category_id  = ec.id ")
201
        cursor_system.execute(query)
202
        rows_meters = cursor_system.fetchall()
203
204
        if rows_meters is not None and len(rows_meters) > 0:
205
            for row in rows_meters:
206
                meter_dict[row[1]] = {'id': row[0], 'unit': row[2]}
207
        # get all offline meters
208
        offline_meter_dict = dict()
209
        query = (" SELECT m.id, m.uuid, ec.unit_of_measure "
210
                 " FROM tbl_offline_meters m, tbl_energy_categories ec "
211
                 " WHERE m.energy_category_id  = ec.id ")
212
        cursor_system.execute(query)
213
        rows_offline_meters = cursor_system.fetchall()
214
215
        if rows_offline_meters is not None and len(rows_offline_meters) > 0:
216
            for row in rows_offline_meters:
217
                offline_meter_dict[row[1]] = {'id': row[0], 'unit': row[2]}
218
        # get all virtual meters
219
        virtual_meter_dict = dict()
220
        query = (" SELECT m.id, m.uuid, ec.unit_of_measure "
221
                 " FROM tbl_virtual_meters m, tbl_energy_categories ec "
222
                 " WHERE m.energy_category_id  = ec.id ")
223
        cursor_system.execute(query)
224
        rows_virtual_meters = cursor_system.fetchall()
225
226
        if rows_virtual_meters is not None and len(rows_virtual_meters) > 0:
227
            for row in rows_virtual_meters:
228
                virtual_meter_dict[row[1]] = {'id': row[0], 'unit': row[2]}
229
230 View Code Duplication
        if fraction_list is not None and len(fraction_list) > 0:
231
            for fraction in fraction_list:
232
                if fraction['numerator_meter_uuid'] in offline_meter_dict:
233
                    fraction['numerator_meter_id'] = offline_meter_dict[fraction['numerator_meter_uuid']]['id']
234
                    fraction['numerator_meter_unit'] = offline_meter_dict[fraction['numerator_meter_uuid']]['unit']
235
                    fraction['numerator_meter_type'] = 'offline_meter'
236
                elif fraction['numerator_meter_uuid'] in virtual_meter_dict:
237
                    fraction['numerator_meter_id'] = virtual_meter_dict[fraction['numerator_meter_uuid']]['id']
238
                    fraction['numerator_meter_unit'] = virtual_meter_dict[fraction['numerator_meter_uuid']]['unit']
239
                    fraction['numerator_meter_type'] = 'virtual_meter'
240
                elif fraction['numerator_meter_uuid'] in meter_dict:
241
                    fraction['numerator_meter_id'] = meter_dict[fraction['numerator_meter_uuid']]['id']
242
                    fraction['numerator_meter_unit'] = meter_dict[fraction['numerator_meter_uuid']]['unit']
243
                    fraction['numerator_meter_type'] = 'meter'
244
245
                if fraction['denominator_meter_uuid'] in offline_meter_dict:
246
                    fraction['denominator_meter_id'] = offline_meter_dict[fraction['denominator_meter_uuid']]['id']
247
                    fraction['denominator_meter_unit'] = offline_meter_dict[fraction['denominator_meter_uuid']]['unit']
248
                    fraction['denominator_meter_type'] = 'offline_meter'
249
                elif fraction['denominator_meter_uuid'] in virtual_meter_dict:
250
                    fraction['denominator_meter_id'] = virtual_meter_dict[fraction['denominator_meter_uuid']]['id']
251
                    fraction['denominator_meter_unit'] = virtual_meter_dict[fraction['denominator_meter_uuid']]['unit']
252
                    fraction['denominator_meter_type'] = 'virtual_meter'
253
                elif fraction['denominator_meter_uuid'] in meter_dict:
254
                    fraction['denominator_meter_id'] = meter_dict[fraction['denominator_meter_uuid']]['id']
255
                    fraction['denominator_meter_unit'] = meter_dict[fraction['denominator_meter_uuid']]['unit']
256
                    fraction['denominator_meter_type'] = 'meter'
257
258
        print(fraction_list)
259
260
        ################################################################################################################
261
        # Step 5: calculate base period fractions
262
        ################################################################################################################
263
        base = dict()
264 View Code Duplication
        if fraction_list is not None and len(fraction_list) > 0:
265
            for fraction in fraction_list:
266
                base[fraction['id']] = dict()
267
                base[fraction['id']]['name'] = fraction['name']
268
                base[fraction['id']]['unit'] = fraction['numerator_meter_unit'] + '/' + \
269
                    fraction['denominator_meter_unit']
270
                base[fraction['id']]['numerator_timestamps'] = list()
271
                base[fraction['id']]['numerator_values'] = list()
272
                base[fraction['id']]['numerator_cumulation'] = Decimal(0.0)
273
                base[fraction['id']]['denominator_timestamps'] = list()
274
                base[fraction['id']]['denominator_values'] = list()
275
                base[fraction['id']]['denominator_cumulation'] = Decimal(0.0)
276
                base[fraction['id']]['timestamps'] = list()
277
                base[fraction['id']]['values'] = list()
278
                base[fraction['id']]['cumulation'] = Decimal(0.0)
279
                # query numerator meter output
280
                if fraction['numerator_meter_type'] == 'meter':
281
                    query = (" SELECT start_datetime_utc, actual_value "
282
                             " FROM tbl_meter_hourly "
283
                             " WHERE meter_id = %s "
284
                             " AND start_datetime_utc >= %s "
285
                             " AND start_datetime_utc < %s "
286
                             " ORDER BY start_datetime_utc ")
287
                elif fraction['numerator_meter_type'] == 'offline_meter':
288
                    query = (" SELECT start_datetime_utc, actual_value "
289
                             " FROM tbl_offline_meter_hourly "
290
                             " WHERE offline_meter_id = %s "
291
                             " AND start_datetime_utc >= %s "
292
                             " AND start_datetime_utc < %s "
293
                             " ORDER BY start_datetime_utc ")
294
                elif fraction['numerator_meter_type'] == 'virtual_meter':
295
                    query = (" SELECT start_datetime_utc, actual_value "
296
                             " FROM tbl_virtual_meter_hourly "
297
                             " WHERE virtual_meter_id = %s "
298
                             " AND start_datetime_utc >= %s "
299
                             " AND start_datetime_utc < %s "
300
                             " ORDER BY start_datetime_utc ")
301
302
                cursor_energy.execute(query, (fraction['numerator_meter_id'],
303
                                              base_start_datetime_utc,
304
                                              base_end_datetime_utc))
305
                rows_numerator_meter_hourly = cursor_energy.fetchall()
306
307
                rows_numerator_meter_periodically = \
308
                    utilities.aggregate_hourly_data_by_period(rows_numerator_meter_hourly,
309
                                                              base_start_datetime_utc,
310
                                                              base_end_datetime_utc,
311
                                                              period_type)
312
                # query denominator meter input
313
                if fraction['denominator_meter_type'] == 'meter':
314
                    query = (" SELECT start_datetime_utc, actual_value "
315
                             " FROM tbl_meter_hourly "
316
                             " WHERE meter_id = %s "
317
                             " AND start_datetime_utc >= %s "
318
                             " AND start_datetime_utc < %s "
319
                             " ORDER BY start_datetime_utc ")
320
                elif fraction['denominator_meter_type'] == 'offline_meter':
321
                    query = (" SELECT start_datetime_utc, actual_value "
322
                             " FROM tbl_offline_meter_hourly "
323
                             " WHERE offline_meter_id = %s "
324
                             " AND start_datetime_utc >= %s "
325
                             " AND start_datetime_utc < %s "
326
                             " ORDER BY start_datetime_utc ")
327
                elif fraction['denominator_meter_type'] == 'virtual_meter':
328
                    query = (" SELECT start_datetime_utc, actual_value "
329
                             " FROM tbl_virtual_meter_hourly "
330
                             " WHERE virtual_meter_id = %s "
331
                             " AND start_datetime_utc >= %s "
332
                             " AND start_datetime_utc < %s "
333
                             " ORDER BY start_datetime_utc ")
334
335
                cursor_energy.execute(query, (fraction['denominator_meter_id'],
336
                                              base_start_datetime_utc,
337
                                              base_end_datetime_utc))
338
                rows_denominator_meter_hourly = cursor_energy.fetchall()
339
340
                rows_denominator_meter_periodically = \
341
                    utilities.aggregate_hourly_data_by_period(rows_denominator_meter_hourly,
342
                                                              base_start_datetime_utc,
343
                                                              base_end_datetime_utc,
344
                                                              period_type)
345
346
                for row_numerator_meter_periodically in rows_numerator_meter_periodically:
347
                    current_datetime_local = row_numerator_meter_periodically[0].replace(tzinfo=timezone.utc) + \
348
                                             timedelta(minutes=timezone_offset)
349
                    if period_type == 'hourly':
350
                        current_datetime = current_datetime_local.strftime('%Y-%m-%dT%H:%M:%S')
351
                    elif period_type == 'daily':
352
                        current_datetime = current_datetime_local.strftime('%Y-%m-%d')
353
                    elif period_type == 'weekly':
354
                        current_datetime = current_datetime_local.strftime('%Y-%m-%d')
355
                    elif period_type == 'monthly':
356
                        current_datetime = current_datetime_local.strftime('%Y-%m')
357
                    elif period_type == 'yearly':
358
                        current_datetime = current_datetime_local.strftime('%Y')
359
360
                    actual_value = Decimal(0.0) if row_numerator_meter_periodically[1] is None \
361
                        else row_numerator_meter_periodically[1]
362
363
                    base[fraction['id']]['numerator_timestamps'].append(current_datetime)
364
                    base[fraction['id']]['numerator_values'].append(actual_value)
365
                    base[fraction['id']]['numerator_cumulation'] += actual_value
366
367
                for row_denominator_meter_periodically in rows_denominator_meter_periodically:
368
                    current_datetime_local = row_denominator_meter_periodically[0].replace(tzinfo=timezone.utc) + \
369
                                             timedelta(minutes=timezone_offset)
370
                    if period_type == 'hourly':
371
                        current_datetime = current_datetime_local.strftime('%Y-%m-%dT%H:%M:%S')
372
                    elif period_type == 'daily':
373
                        current_datetime = current_datetime_local.strftime('%Y-%m-%d')
374
                    elif period_type == 'weekly':
375
                        current_datetime = current_datetime_local.strftime('%Y-%m-%d')
376
                    elif period_type == 'monthly':
377
                        current_datetime = current_datetime_local.strftime('%Y-%m')
378
                    elif period_type == 'yearly':
379
                        current_datetime = current_datetime_local.strftime('%Y')
380
381
                    actual_value = Decimal(0.0) if row_denominator_meter_periodically[1] is None \
382
                        else row_denominator_meter_periodically[1]
383
384
                    base[fraction['id']]['denominator_timestamps'].append(current_datetime)
385
                    base[fraction['id']]['denominator_values'].append(actual_value)
386
                    base[fraction['id']]['denominator_cumulation'] += actual_value
387
388
                for i in range(len(base[fraction['id']]['denominator_timestamps'])):
389
                    timestamp = base[fraction['id']]['denominator_timestamps'][i]
390
                    base[fraction['id']]['timestamps'].append(timestamp)
391
                    value = (base[fraction['id']]['numerator_values'][i] /
392
                             base[fraction['id']]['denominator_values'][i]) \
393
                        if base[fraction['id']]['denominator_values'][i] > Decimal(0.0) else Decimal(0.0)
394
                    base[fraction['id']]['values'].append(value)
395
396
                cumulation = (base[fraction['id']]['numerator_cumulation'] /
397
                              base[fraction['id']]['denominator_cumulation']) \
398
                    if base[fraction['id']]['denominator_cumulation'] > Decimal(0.0) else Decimal(0.0)
399
                base[fraction['id']]['cumulation'] = cumulation
400
401
        ################################################################################################################
402
        # Step 6: calculate reporting period fractions
403
        ################################################################################################################
404
        reporting = dict()
405 View Code Duplication
        if fraction_list is not None and len(fraction_list) > 0:
406
            for fraction in fraction_list:
407
                reporting[fraction['id']] = dict()
408
                reporting[fraction['id']]['name'] = fraction['name']
409
                reporting[fraction['id']]['unit'] = fraction['numerator_meter_unit'] + '/' + \
410
                    fraction['denominator_meter_unit']
411
                reporting[fraction['id']]['numerator_timestamps'] = list()
412
                reporting[fraction['id']]['numerator_values'] = list()
413
                reporting[fraction['id']]['numerator_cumulation'] = Decimal(0.0)
414
                reporting[fraction['id']]['denominator_timestamps'] = list()
415
                reporting[fraction['id']]['denominator_values'] = list()
416
                reporting[fraction['id']]['denominator_cumulation'] = Decimal(0.0)
417
                reporting[fraction['id']]['timestamps'] = list()
418
                reporting[fraction['id']]['values'] = list()
419
                reporting[fraction['id']]['cumulation'] = Decimal(0.0)
420
                # query numerator meter output
421
                if fraction['numerator_meter_type'] == 'meter':
422
                    query = (" SELECT start_datetime_utc, actual_value "
423
                             " FROM tbl_meter_hourly "
424
                             " WHERE meter_id = %s "
425
                             " AND start_datetime_utc >= %s "
426
                             " AND start_datetime_utc < %s "
427
                             " ORDER BY start_datetime_utc ")
428
                elif fraction['numerator_meter_type'] == 'offline_meter':
429
                    query = (" SELECT start_datetime_utc, actual_value "
430
                             " FROM tbl_offline_meter_hourly "
431
                             " WHERE offline_meter_id = %s "
432
                             " AND start_datetime_utc >= %s "
433
                             " AND start_datetime_utc < %s "
434
                             " ORDER BY start_datetime_utc ")
435
                elif fraction['numerator_meter_type'] == 'virtual_meter':
436
                    query = (" SELECT start_datetime_utc, actual_value "
437
                             " FROM tbl_virtual_meter_hourly "
438
                             " WHERE virtual_meter_id = %s "
439
                             " AND start_datetime_utc >= %s "
440
                             " AND start_datetime_utc < %s "
441
                             " ORDER BY start_datetime_utc ")
442
443
                cursor_energy.execute(query, (fraction['numerator_meter_id'],
444
                                              reporting_start_datetime_utc,
445
                                              reporting_end_datetime_utc))
446
                rows_numerator_meter_hourly = cursor_energy.fetchall()
447
448
                rows_numerator_meter_periodically = \
449
                    utilities.aggregate_hourly_data_by_period(rows_numerator_meter_hourly,
450
                                                              reporting_start_datetime_utc,
451
                                                              reporting_end_datetime_utc,
452
                                                              period_type)
453
                # query denominator meter input
454
                if fraction['denominator_meter_type'] == 'meter':
455
                    query = (" SELECT start_datetime_utc, actual_value "
456
                             " FROM tbl_meter_hourly "
457
                             " WHERE meter_id = %s "
458
                             " AND start_datetime_utc >= %s "
459
                             " AND start_datetime_utc < %s "
460
                             " ORDER BY start_datetime_utc ")
461
                elif fraction['denominator_meter_type'] == 'offline_meter':
462
                    query = (" SELECT start_datetime_utc, actual_value "
463
                             " FROM tbl_offline_meter_hourly "
464
                             " WHERE offline_meter_id = %s "
465
                             " AND start_datetime_utc >= %s "
466
                             " AND start_datetime_utc < %s "
467
                             " ORDER BY start_datetime_utc ")
468
                elif fraction['denominator_meter_type'] == 'virtual_meter':
469
                    query = (" SELECT start_datetime_utc, actual_value "
470
                             " FROM tbl_virtual_meter_hourly "
471
                             " WHERE virtual_meter_id = %s "
472
                             " AND start_datetime_utc >= %s "
473
                             " AND start_datetime_utc < %s "
474
                             " ORDER BY start_datetime_utc ")
475
476
                cursor_energy.execute(query, (fraction['denominator_meter_id'],
477
                                              reporting_start_datetime_utc,
478
                                              reporting_end_datetime_utc))
479
                rows_denominator_meter_hourly = cursor_energy.fetchall()
480
481
                rows_denominator_meter_periodically = \
482
                    utilities.aggregate_hourly_data_by_period(rows_denominator_meter_hourly,
483
                                                              reporting_start_datetime_utc,
484
                                                              reporting_end_datetime_utc,
485
                                                              period_type)
486
487
                for row_numerator_meter_periodically in rows_numerator_meter_periodically:
488
                    current_datetime_local = row_numerator_meter_periodically[0].replace(tzinfo=timezone.utc) + \
489
                                             timedelta(minutes=timezone_offset)
490
                    if period_type == 'hourly':
491
                        current_datetime = current_datetime_local.strftime('%Y-%m-%dT%H:%M:%S')
492
                    elif period_type == 'daily':
493
                        current_datetime = current_datetime_local.strftime('%Y-%m-%d')
494
                    elif period_type == 'weekly':
495
                        current_datetime = current_datetime_local.strftime('%Y-%m-%d')
496
                    elif period_type == 'monthly':
497
                        current_datetime = current_datetime_local.strftime('%Y-%m')
498
                    elif period_type == 'yearly':
499
                        current_datetime = current_datetime_local.strftime('%Y')
500
501
                    actual_value = Decimal(0.0) if row_numerator_meter_periodically[1] is None \
502
                        else row_numerator_meter_periodically[1]
503
504
                    reporting[fraction['id']]['numerator_timestamps'].append(current_datetime)
505
                    reporting[fraction['id']]['numerator_values'].append(actual_value)
506
                    reporting[fraction['id']]['numerator_cumulation'] += actual_value
507
508
                for row_denominator_meter_periodically in rows_denominator_meter_periodically:
509
                    current_datetime_local = row_denominator_meter_periodically[0].replace(tzinfo=timezone.utc) + \
510
                                             timedelta(minutes=timezone_offset)
511
                    if period_type == 'hourly':
512
                        current_datetime = current_datetime_local.strftime('%Y-%m-%dT%H:%M:%S')
513
                    elif period_type == 'daily':
514
                        current_datetime = current_datetime_local.strftime('%Y-%m-%d')
515
                    elif period_type == 'weekly':
516
                        current_datetime = current_datetime_local.strftime('%Y-%m-%d')
517
                    elif period_type == 'monthly':
518
                        current_datetime = current_datetime_local.strftime('%Y-%m')
519
                    elif period_type == 'yearly':
520
                        current_datetime = current_datetime_local.strftime('%Y')
521
522
                    actual_value = Decimal(0.0) if row_denominator_meter_periodically[1] is None \
523
                        else row_denominator_meter_periodically[1]
524
525
                    reporting[fraction['id']]['denominator_timestamps'].append(current_datetime)
526
                    reporting[fraction['id']]['denominator_values'].append(actual_value)
527
                    reporting[fraction['id']]['denominator_cumulation'] += actual_value
528
529
                for i in range(len(reporting[fraction['id']]['denominator_timestamps'])):
530
                    timestamp = reporting[fraction['id']]['denominator_timestamps'][i]
531
                    reporting[fraction['id']]['timestamps'].append(timestamp)
532
                    value = reporting[fraction['id']]['numerator_values'][i] / \
533
                        reporting[fraction['id']]['denominator_values'][i] \
534
                        if reporting[fraction['id']]['denominator_values'][i] > Decimal(0.0) else Decimal(0.0)
535
                    reporting[fraction['id']]['values'].append(value)
536
537
                cumulation = (reporting[fraction['id']]['numerator_cumulation'] /
538
                              reporting[fraction['id']]['denominator_cumulation']) \
539
                    if reporting[fraction['id']]['denominator_cumulation'] > Decimal(0.0) else Decimal(0.0)
540
                reporting[fraction['id']]['cumulation'] = cumulation
541
542
        ################################################################################################################
543
        # Step 7: query associated points data
544
        ################################################################################################################
545
        parameters_data = dict()
546
        parameters_data['names'] = list()
547
        parameters_data['timestamps'] = list()
548
        parameters_data['values'] = list()
549
550
        for point in point_list:
551
            point_values = []
552
            point_timestamps = []
553
            if point['object_type'] == 'ANALOG_VALUE':
554
                query = (" SELECT utc_date_time, actual_value "
555
                         " FROM tbl_analog_value "
556
                         " WHERE point_id = %s "
557
                         "       AND utc_date_time BETWEEN %s AND %s "
558
                         " ORDER BY utc_date_time ")
559
                cursor_historical.execute(query, (point['id'],
560
                                                  reporting_start_datetime_utc,
561
                                                  reporting_end_datetime_utc))
562
                rows = cursor_historical.fetchall()
563
564
                if rows is not None and len(rows) > 0:
565
                    for row in rows:
566
                        current_datetime_local = row[0].replace(tzinfo=timezone.utc) + \
567
                                                 timedelta(minutes=timezone_offset)
568
                        current_datetime = current_datetime_local.strftime('%Y-%m-%dT%H:%M:%S')
569
                        point_timestamps.append(current_datetime)
570
                        point_values.append(row[1])
571
572
            elif point['object_type'] == 'ENERGY_VALUE':
573
                query = (" SELECT utc_date_time, actual_value "
574
                         " FROM tbl_energy_value "
575
                         " WHERE point_id = %s "
576
                         "       AND utc_date_time BETWEEN %s AND %s "
577
                         " ORDER BY utc_date_time ")
578
                cursor_historical.execute(query, (point['id'],
579
                                                  reporting_start_datetime_utc,
580
                                                  reporting_end_datetime_utc))
581
                rows = cursor_historical.fetchall()
582
583
                if rows is not None and len(rows) > 0:
584
                    for row in rows:
585
                        current_datetime_local = row[0].replace(tzinfo=timezone.utc) + \
586
                                                 timedelta(minutes=timezone_offset)
587
                        current_datetime = current_datetime_local.strftime('%Y-%m-%dT%H:%M:%S')
588
                        point_timestamps.append(current_datetime)
589
                        point_values.append(row[1])
590
            elif point['object_type'] == 'DIGITAL_VALUE':
591
                query = (" SELECT utc_date_time, actual_value "
592
                         " FROM tbl_digital_value "
593
                         " WHERE point_id = %s "
594
                         "       AND utc_date_time BETWEEN %s AND %s "
595
                         " ORDER BY utc_date_time ")
596
                cursor_historical.execute(query, (point['id'],
597
                                                  reporting_start_datetime_utc,
598
                                                  reporting_end_datetime_utc))
599
                rows = cursor_historical.fetchall()
600
601
                if rows is not None and len(rows) > 0:
602
                    for row in rows:
603
                        current_datetime_local = row[0].replace(tzinfo=timezone.utc) + \
604
                                                 timedelta(minutes=timezone_offset)
605
                        current_datetime = current_datetime_local.strftime('%Y-%m-%dT%H:%M:%S')
606
                        point_timestamps.append(current_datetime)
607
                        point_values.append(row[1])
608
609
            parameters_data['names'].append(point['name'] + ' (' + point['units'] + ')')
610
            parameters_data['timestamps'].append(point_timestamps)
611
            parameters_data['values'].append(point_values)
612
613
        ################################################################################################################
614
        # Step 8: construct the report
615
        ################################################################################################################
616
        if cursor_system:
617
            cursor_system.close()
618
        if cnx_system:
619
            cnx_system.disconnect()
620
621
        if cursor_energy:
622
            cursor_energy.close()
623
        if cnx_energy:
624
            cnx_energy.disconnect()
625
626
        result = dict()
627
628
        result['equipment'] = dict()
629
        result['equipment']['name'] = equipment['name']
630
631
        result['base_period_efficiency'] = dict()
632
        result['base_period_efficiency']['timestamps'] = list()
633
        result['base_period_efficiency']['values'] = list()
634
        result['base_period_efficiency']['cumulations'] = list()
635
636
        result['reporting_period_efficiency'] = dict()
637
        result['reporting_period_efficiency']['names'] = list()
638
        result['reporting_period_efficiency']['units'] = list()
639
        result['reporting_period_efficiency']['timestamps'] = list()
640
        result['reporting_period_efficiency']['values'] = list()
641
        result['reporting_period_efficiency']['cumulations'] = list()
642
        result['reporting_period_efficiency']['increment_rates'] = list()
643 View Code Duplication
        if fraction_list is not None and len(fraction_list) > 0:
0 ignored issues
show
This code seems to be duplicated in your project.
Loading history...
644
            for fraction in fraction_list:
645
                result['base_period_efficiency']['timestamps'].append(base[fraction['id']]['timestamps'])
646
                result['base_period_efficiency']['values'].append(base[fraction['id']]['values'])
647
                result['base_period_efficiency']['cumulations'].append(base[fraction['id']]['cumulation'])
648
                result['reporting_period_efficiency']['names'].append(reporting[fraction['id']]['name'])
649
                result['reporting_period_efficiency']['units'].append(reporting[fraction['id']]['unit'])
650
                result['reporting_period_efficiency']['timestamps'].append(reporting[fraction['id']]['timestamps'])
651
                result['reporting_period_efficiency']['values'].append(reporting[fraction['id']]['values'])
652
                result['reporting_period_efficiency']['cumulations'].append(reporting[fraction['id']]['cumulation'])
653
                result['reporting_period_efficiency']['increment_rates'].append(
654
                    (reporting[fraction['id']]['cumulation'] - base[fraction['id']]['cumulation']) /
655
                    base[fraction['id']]['cumulation'] if base[fraction['id']]['cumulation'] > Decimal(0.0) else None)
656
657
        result['parameters'] = {
658
            "names": parameters_data['names'],
659
            "timestamps": parameters_data['timestamps'],
660
            "values": parameters_data['values']
661
        }
662
663
        # export result to Excel file and then encode the file to base64 string
664
        result['excel_bytes_base64'] = excelexporters.equipmentefficiency.export(result,
665
                                                                                 equipment['name'],
666
                                                                                 reporting_start_datetime_local,
667
                                                                                 reporting_end_datetime_local,
668
                                                                                 period_type)
669
670
        resp.text = json.dumps(result)
671