Passed
Push — master ( dc4cf6...d9c3b0 )
by Guangyu
02:47 queued 10s
created

reports.spacesaving.Reporting.__init__()   A

Complexity

Conditions 1

Size

Total Lines 3
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 3
nop 0
dl 0
loc 3
rs 10
c 0
b 0
f 0
1
import falcon
2
import simplejson as json
3
import mysql.connector
4
import config
5
from datetime import datetime, timedelta, timezone
6
import utilities
7
from decimal import *
8
9
10
class Reporting:
11
    @staticmethod
12
    def __init__():
13
        pass
14
15
    @staticmethod
16
    def on_options(req, resp):
17
        resp.status = falcon.HTTP_200
18
19
    ####################################################################################################################
20
    # PROCEDURES
21
    # Step 1: valid parameters
22
    # Step 2: query the space
23
    # Step 3: query energy categories
24
    # Step 4: query associated sensors
25
    # Step 5: query associated points
26
    # Step 6: query child spaces
27
    # Step 7: query base period energy saving
28
    # Step 8: query reporting period energy saving
29
    # Step 9: query tariff data
30
    # Step 10: query associated sensors and points data
31
    # Step 11: query child spaces energy saving
32
    # Step 12: construct the report
33
    ####################################################################################################################
34
    @staticmethod
35
    def on_get(req, resp):
36
        print(req.params)
37
        space_id = req.params.get('spaceid')
38
        period_type = req.params.get('periodtype')
39
        base_start_datetime_local = req.params.get('baseperiodstartdatetime')
40
        base_end_datetime_local = req.params.get('baseperiodenddatetime')
41
        reporting_start_datetime_local = req.params.get('reportingperiodstartdatetime')
42
        reporting_end_datetime_local = req.params.get('reportingperiodenddatetime')
43
44
        ################################################################################################################
45
        # Step 1: valid parameters
46
        ################################################################################################################
47
        if space_id is None:
48
            raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST', description='API.INVALID_SPACE_ID')
49
        else:
50
            space_id = str.strip(space_id)
51
            if not space_id.isdigit() or int(space_id) <= 0:
52
                raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST', description='API.INVALID_SPACE_ID')
53
54
        if period_type is None:
55
            raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST', description='API.INVALID_PERIOD_TYPE')
56
        else:
57
            period_type = str.strip(period_type)
58
            if period_type not in ['hourly', 'daily', 'monthly', 'yearly']:
59
                raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST', description='API.INVALID_PERIOD_TYPE')
60
61
        timezone_offset = int(config.utc_offset[1:3]) * 60 + int(config.utc_offset[4:6])
62
        if config.utc_offset[0] == '-':
63
            timezone_offset = -timezone_offset
64
65
        base_start_datetime_utc = None
66
        if base_start_datetime_local is not None and len(str.strip(base_start_datetime_local)) > 0:
67
            base_start_datetime_local = str.strip(base_start_datetime_local)
68
            try:
69
                base_start_datetime_utc = datetime.strptime(base_start_datetime_local,
70
                                                            '%Y-%m-%dT%H:%M:%S').replace(tzinfo=timezone.utc) - \
71
                    timedelta(minutes=timezone_offset)
72
            except ValueError:
73
                raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST',
74
                                       description="API.INVALID_BASE_PERIOD_BEGINS_DATETIME")
75
76
        base_end_datetime_utc = None
77
        if base_end_datetime_local is not None and len(str.strip(base_end_datetime_local)) > 0:
78
            base_end_datetime_local = str.strip(base_end_datetime_local)
79
            try:
80
                base_end_datetime_utc = datetime.strptime(base_end_datetime_local,
81
                                                          '%Y-%m-%dT%H:%M:%S').replace(tzinfo=timezone.utc) - \
82
                    timedelta(minutes=timezone_offset)
83
            except ValueError:
84
                raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST',
85
                                       description="API.INVALID_BASE_PERIOD_ENDS_DATETIME")
86
87
        if base_start_datetime_utc is not None and base_end_datetime_utc is not None and \
88
                base_start_datetime_utc >= base_end_datetime_utc:
89
            raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST',
90
                                   description='API.INVALID_BASE_PERIOD_ENDS_DATETIME')
91
92
        if reporting_start_datetime_local is None:
93
            raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST',
94
                                   description="API.INVALID_REPORTING_PERIOD_BEGINS_DATETIME")
95
        else:
96
            reporting_start_datetime_local = str.strip(reporting_start_datetime_local)
97
            try:
98
                reporting_start_datetime_utc = datetime.strptime(reporting_start_datetime_local,
99
                                                                 '%Y-%m-%dT%H:%M:%S').replace(tzinfo=timezone.utc) - \
100
                    timedelta(minutes=timezone_offset)
101
            except ValueError:
102
                raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST',
103
                                       description="API.INVALID_REPORTING_PERIOD_BEGINS_DATETIME")
104
105
        if reporting_end_datetime_local is None:
106
            raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST',
107
                                   description="API.INVALID_REPORTING_PERIOD_ENDS_DATETIME")
108
        else:
109
            reporting_end_datetime_local = str.strip(reporting_end_datetime_local)
110
            try:
111
                reporting_end_datetime_utc = datetime.strptime(reporting_end_datetime_local,
112
                                                               '%Y-%m-%dT%H:%M:%S').replace(tzinfo=timezone.utc) - \
113
                    timedelta(minutes=timezone_offset)
114
            except ValueError:
115
                raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST',
116
                                       description="API.INVALID_REPORTING_PERIOD_ENDS_DATETIME")
117
118
        if reporting_start_datetime_utc >= reporting_end_datetime_utc:
119
            raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST',
120
                                   description='API.INVALID_REPORTING_PERIOD_ENDS_DATETIME')
121
122
        ################################################################################################################
123
        # Step 2: query the space
124
        ################################################################################################################
125
        cnx_system = mysql.connector.connect(**config.myems_system_db)
126
        cursor_system = cnx_system.cursor()
127
128
        cnx_energy = mysql.connector.connect(**config.myems_energy_db)
129
        cursor_energy = cnx_energy.cursor()
130
131
        cnx_energy_baseline = mysql.connector.connect(**config.myems_energy_baseline_db)
132
        cursor_energy_baseline = cnx_energy_baseline.cursor()
133
134
        cnx_historical = mysql.connector.connect(**config.myems_historical_db)
135
        cursor_historical = cnx_historical.cursor()
136
137
        cursor_system.execute(" SELECT id, name, area, cost_center_id "
138
                              " FROM tbl_spaces "
139
                              " WHERE id = %s ", (space_id,))
140
        row_space = cursor_system.fetchone()
141
        if row_space is None:
142
            if cursor_system:
143
                cursor_system.close()
144
            if cnx_system:
145
                cnx_system.disconnect()
146
147
            if cursor_energy:
148
                cursor_energy.close()
149
            if cnx_energy:
150
                cnx_energy.disconnect()
151
152
            if cursor_energy_baseline:
153
                cursor_energy_baseline.close()
154
            if cnx_energy_baseline:
155
                cnx_energy_baseline.disconnect()
156
157
            if cnx_historical:
158
                cnx_historical.close()
159
            if cursor_historical:
160
                cursor_historical.disconnect()
161
            raise falcon.HTTPError(falcon.HTTP_404, title='API.NOT_FOUND', description='API.SPACE_NOT_FOUND')
162
163
        space = dict()
164
        space['id'] = row_space[0]
165
        space['name'] = row_space[1]
166
        space['area'] = row_space[2]
167
        space['cost_center_id'] = row_space[3]
168
169
        ################################################################################################################
170
        # Step 3: query energy categories
171
        ################################################################################################################
172
        energy_category_set = set()
173
        # query energy categories in base period
174
        cursor_energy.execute(" SELECT DISTINCT(energy_category_id) "
175
                              " FROM tbl_space_input_category_hourly "
176
                              " WHERE space_id = %s "
177
                              "     AND start_datetime_utc >= %s "
178
                              "     AND start_datetime_utc < %s ",
179
                              (space['id'], base_start_datetime_utc, base_end_datetime_utc))
180
        rows_energy_categories = cursor_energy.fetchall()
181
        if rows_energy_categories is not None or len(rows_energy_categories) > 0:
182
            for row_energy_category in rows_energy_categories:
183
                energy_category_set.add(row_energy_category[0])
184
185
        # query energy categories in reporting period
186
        cursor_energy.execute(" SELECT DISTINCT(energy_category_id) "
187
                              " FROM tbl_space_input_category_hourly "
188
                              " WHERE space_id = %s "
189
                              "     AND start_datetime_utc >= %s "
190
                              "     AND start_datetime_utc < %s ",
191
                              (space['id'], reporting_start_datetime_utc, reporting_end_datetime_utc))
192
        rows_energy_categories = cursor_energy.fetchall()
193
        if rows_energy_categories is not None or len(rows_energy_categories) > 0:
194
            for row_energy_category in rows_energy_categories:
195
                energy_category_set.add(row_energy_category[0])
196
197
        # query all energy categories in base period and reporting period
198
        cursor_system.execute(" SELECT id, name, unit_of_measure, kgce, kgco2e "
199
                              " FROM tbl_energy_categories "
200
                              " ORDER BY id ", )
201
        rows_energy_categories = cursor_system.fetchall()
202
        if rows_energy_categories is None or len(rows_energy_categories) == 0:
203
            if cursor_system:
204
                cursor_system.close()
205
            if cnx_system:
206
                cnx_system.disconnect()
207
208
            if cursor_energy:
209
                cursor_energy.close()
210
            if cnx_energy:
211
                cnx_energy.disconnect()
212
213
            if cursor_energy_baseline:
214
                cursor_energy_baseline.close()
215
            if cnx_energy_baseline:
216
                cnx_energy_baseline.disconnect()
217
218
            if cnx_historical:
219
                cnx_historical.close()
220
            if cursor_historical:
221
                cursor_historical.disconnect()
222
            raise falcon.HTTPError(falcon.HTTP_404,
223
                                   title='API.NOT_FOUND',
224
                                   description='API.ENERGY_CATEGORY_NOT_FOUND')
225
        energy_category_dict = dict()
226
        for row_energy_category in rows_energy_categories:
227
            if row_energy_category[0] in energy_category_set:
228
                energy_category_dict[row_energy_category[0]] = {"name": row_energy_category[1],
229
                                                                "unit_of_measure": row_energy_category[2],
230
                                                                "kgce": row_energy_category[3],
231
                                                                "kgco2e": row_energy_category[4]}
232
233
        ################################################################################################################
234
        # Step 4: query associated sensors
235
        ################################################################################################################
236
        point_list = list()
237
        cursor_system.execute(" SELECT po.id, po.name, po.units, po.object_type  "
238
                              " FROM tbl_spaces sp, tbl_sensors se, tbl_spaces_sensors spse, "
239
                              "      tbl_points po, tbl_sensors_points sepo "
240
                              " WHERE sp.id = %s AND sp.id = spse.space_id AND spse.sensor_id = se.id "
241
                              "       AND se.id = sepo.sensor_id AND sepo.point_id = po.id "
242
                              " ORDER BY po.id ", (space['id'], ))
243
        rows_points = cursor_system.fetchall()
244
        if rows_points is not None and len(rows_points) > 0:
245
            for row in rows_points:
246
                point_list.append({"id": row[0], "name": row[1], "units": row[2], "object_type": row[3]})
247
248
        ################################################################################################################
249
        # Step 5: query associated points
250
        ################################################################################################################
251
        cursor_system.execute(" SELECT po.id, po.name, po.units, po.object_type  "
252
                              " FROM tbl_spaces sp, tbl_spaces_points sppo, tbl_points po "
253
                              " WHERE sp.id = %s AND sp.id = sppo.space_id AND sppo.point_id = po.id "
254
                              " ORDER BY po.id ", (space['id'], ))
255
        rows_points = cursor_system.fetchall()
256
        if rows_points is not None and len(rows_points) > 0:
257
            for row in rows_points:
258
                point_list.append({"id": row[0], "name": row[1], "units": row[2], "object_type": row[3]})
259
260
        ################################################################################################################
261
        # Step 6: query child spaces
262
        ################################################################################################################
263
        child_space_list = list()
264
        cursor_system.execute(" SELECT id, name  "
265
                              " FROM tbl_spaces "
266
                              " WHERE parent_space_id = %s "
267
                              " ORDER BY id ", (space['id'], ))
268
        rows_child_spaces = cursor_system.fetchall()
269
        if rows_child_spaces is not None and len(rows_child_spaces) > 0:
270
            for row in rows_child_spaces:
271
                child_space_list.append({"id": row[0], "name": row[1]})
272
273
        ################################################################################################################
274
        # Step 7: query base period energy saving
275
        ################################################################################################################
276
        base = dict()
277
        if energy_category_set is not None and len(energy_category_set) > 0:
278
            for energy_category_id in energy_category_set:
279
                kgce = energy_category_dict[energy_category_id]['kgce']
280
                kgco2e = energy_category_dict[energy_category_id]['kgco2e']
281
282
                base[energy_category_id] = dict()
283
                base[energy_category_id]['timestamps'] = list()
284
                base[energy_category_id]['values_baseline'] = list()
285
                base[energy_category_id]['values_actual'] = list()
286
                base[energy_category_id]['values_saving'] = list()
287
                base[energy_category_id]['subtotal_baseline'] = Decimal(0.0)
288
                base[energy_category_id]['subtotal_actual'] = Decimal(0.0)
289
                base[energy_category_id]['subtotal_saving'] = Decimal(0.0)
290
                base[energy_category_id]['subtotal_in_kgce_baseline'] = Decimal(0.0)
291
                base[energy_category_id]['subtotal_in_kgce_actual'] = Decimal(0.0)
292
                base[energy_category_id]['subtotal_in_kgce_saving'] = Decimal(0.0)
293
                base[energy_category_id]['subtotal_in_kgco2e_baseline'] = Decimal(0.0)
294
                base[energy_category_id]['subtotal_in_kgco2e_actual'] = Decimal(0.0)
295
                base[energy_category_id]['subtotal_in_kgco2e_saving'] = Decimal(0.0)
296
                # query base period's energy baseline
297
                cursor_energy_baseline.execute(" SELECT start_datetime_utc, actual_value "
298
                                               " FROM tbl_space_input_category_hourly "
299
                                               " WHERE space_id = %s "
300
                                               "     AND energy_category_id = %s "
301
                                               "     AND start_datetime_utc >= %s "
302
                                               "     AND start_datetime_utc < %s "
303
                                               " ORDER BY start_datetime_utc ",
304
                                               (space['id'],
305
                                                energy_category_id,
306
                                                base_start_datetime_utc,
307
                                                base_end_datetime_utc))
308
                rows_space_hourly = cursor_energy_baseline.fetchall()
309
310
                rows_space_periodically = utilities.aggregate_hourly_data_by_period(rows_space_hourly,
311
                                                                                    base_start_datetime_utc,
312
                                                                                    base_end_datetime_utc,
313
                                                                                    period_type)
314
                for row_space_periodically in rows_space_periodically:
315
                    current_datetime_local = row_space_periodically[0].replace(tzinfo=timezone.utc) + \
316
                                             timedelta(minutes=timezone_offset)
317
                    if period_type == 'hourly':
318
                        current_datetime = current_datetime_local.strftime('%Y-%m-%dT%H:%M:%S')
319
                    elif period_type == 'daily':
320
                        current_datetime = current_datetime_local.strftime('%Y-%m-%d')
321
                    elif period_type == 'monthly':
322
                        current_datetime = current_datetime_local.strftime('%Y-%m')
323
                    elif period_type == 'yearly':
324
                        current_datetime = current_datetime_local.strftime('%Y')
325
326
                    baseline_value = Decimal(0.0) if row_space_periodically[1] is None else row_space_periodically[1]
327
                    base[energy_category_id]['timestamps'].append(current_datetime)
0 ignored issues
show
introduced by
The variable current_datetime does not seem to be defined for all execution paths.
Loading history...
328
                    base[energy_category_id]['values_baseline'].append(baseline_value)
329
                    base[energy_category_id]['subtotal_baseline'] += baseline_value
330
                    base[energy_category_id]['subtotal_in_kgce_baseline'] += baseline_value * kgce
331
                    base[energy_category_id]['subtotal_in_kgco2e_baseline'] += baseline_value * kgco2e
332
333
                # query base period's energy actual
334
                cursor_energy.execute(" SELECT start_datetime_utc, actual_value "
335
                                      " FROM tbl_space_input_category_hourly "
336
                                      " WHERE space_id = %s "
337
                                      "     AND energy_category_id = %s "
338
                                      "     AND start_datetime_utc >= %s "
339
                                      "     AND start_datetime_utc < %s "
340
                                      " ORDER BY start_datetime_utc ",
341
                                      (space['id'],
342
                                       energy_category_id,
343
                                       base_start_datetime_utc,
344
                                       base_end_datetime_utc))
345
                rows_space_hourly = cursor_energy.fetchall()
346
347
                rows_space_periodically = utilities.aggregate_hourly_data_by_period(rows_space_hourly,
348
                                                                                    base_start_datetime_utc,
349
                                                                                    base_end_datetime_utc,
350
                                                                                    period_type)
351
                for row_space_periodically in rows_space_periodically:
352
                    current_datetime_local = row_space_periodically[0].replace(tzinfo=timezone.utc) + \
353
                                             timedelta(minutes=timezone_offset)
354
                    if period_type == 'hourly':
355
                        current_datetime = current_datetime_local.strftime('%Y-%m-%dT%H:%M:%S')
356
                    elif period_type == 'daily':
357
                        current_datetime = current_datetime_local.strftime('%Y-%m-%d')
358
                    elif period_type == 'monthly':
359
                        current_datetime = current_datetime_local.strftime('%Y-%m')
360
                    elif period_type == 'yearly':
361
                        current_datetime = current_datetime_local.strftime('%Y')
362
363
                    actual_value = Decimal(0.0) if row_space_periodically[1] is None else row_space_periodically[1]
364
                    base[energy_category_id]['values_actual'].append(actual_value)
365
                    base[energy_category_id]['subtotal_actual'] += actual_value
366
                    base[energy_category_id]['subtotal_in_kgce_actual'] += actual_value * kgce
367
                    base[energy_category_id]['subtotal_in_kgco2e_actual'] += actual_value * kgco2e
368
369
                # calculate base period's energy savings
370
                for i in range(len(base[energy_category_id]['values_baseline'])):
371
                    base[energy_category_id]['values_saving'].append(
372
                        base[energy_category_id]['values_baseline'][i] -
373
                        base[energy_category_id]['values_actual'][i])
374
375
                base[energy_category_id]['subtotal_saving'] = \
376
                    base[energy_category_id]['subtotal_baseline'] - \
377
                    base[energy_category_id]['subtotal_actual']
378
                base[energy_category_id]['subtotal_in_kgce_saving'] = \
379
                    base[energy_category_id]['subtotal_in_kgce_baseline'] - \
380
                    base[energy_category_id]['subtotal_in_kgce_actual']
381
                base[energy_category_id]['subtotal_in_kgco2e_saving'] = \
382
                    base[energy_category_id]['subtotal_in_kgco2e_baseline'] - \
383
                    base[energy_category_id]['subtotal_in_kgco2e_actual']
384
        ################################################################################################################
385
        # Step 8: query reporting period energy saving
386
        ################################################################################################################
387
        reporting = dict()
388
        if energy_category_set is not None and len(energy_category_set) > 0:
389
            for energy_category_id in energy_category_set:
390
                kgce = energy_category_dict[energy_category_id]['kgce']
391
                kgco2e = energy_category_dict[energy_category_id]['kgco2e']
392
393
                reporting[energy_category_id] = dict()
394
                reporting[energy_category_id]['timestamps'] = list()
395
                reporting[energy_category_id]['values_baseline'] = list()
396
                reporting[energy_category_id]['values_actual'] = list()
397
                reporting[energy_category_id]['values_saving'] = list()
398
                reporting[energy_category_id]['subtotal_baseline'] = Decimal(0.0)
399
                reporting[energy_category_id]['subtotal_actual'] = Decimal(0.0)
400
                reporting[energy_category_id]['subtotal_saving'] = Decimal(0.0)
401
                reporting[energy_category_id]['subtotal_in_kgce_baseline'] = Decimal(0.0)
402
                reporting[energy_category_id]['subtotal_in_kgce_actual'] = Decimal(0.0)
403
                reporting[energy_category_id]['subtotal_in_kgce_saving'] = Decimal(0.0)
404
                reporting[energy_category_id]['subtotal_in_kgco2e_baseline'] = Decimal(0.0)
405
                reporting[energy_category_id]['subtotal_in_kgco2e_actual'] = Decimal(0.0)
406
                reporting[energy_category_id]['subtotal_in_kgco2e_saving'] = Decimal(0.0)
407
                # query reporting period's energy baseline
408
                cursor_energy_baseline.execute(" SELECT start_datetime_utc, actual_value "
409
                                               " FROM tbl_space_input_category_hourly "
410
                                               " WHERE space_id = %s "
411
                                               "     AND energy_category_id = %s "
412
                                               "     AND start_datetime_utc >= %s "
413
                                               "     AND start_datetime_utc < %s "
414
                                               " ORDER BY start_datetime_utc ",
415
                                               (space['id'],
416
                                                energy_category_id,
417
                                                reporting_start_datetime_utc,
418
                                                reporting_end_datetime_utc))
419
                rows_space_hourly = cursor_energy_baseline.fetchall()
420
421
                rows_space_periodically = utilities.aggregate_hourly_data_by_period(rows_space_hourly,
422
                                                                                    reporting_start_datetime_utc,
423
                                                                                    reporting_end_datetime_utc,
424
                                                                                    period_type)
425
                for row_space_periodically in rows_space_periodically:
426
                    current_datetime_local = row_space_periodically[0].replace(tzinfo=timezone.utc) + \
427
                                             timedelta(minutes=timezone_offset)
428
                    if period_type == 'hourly':
429
                        current_datetime = current_datetime_local.strftime('%Y-%m-%dT%H:%M:%S')
430
                    elif period_type == 'daily':
431
                        current_datetime = current_datetime_local.strftime('%Y-%m-%d')
432
                    elif period_type == 'monthly':
433
                        current_datetime = current_datetime_local.strftime('%Y-%m')
434
                    elif period_type == 'yearly':
435
                        current_datetime = current_datetime_local.strftime('%Y')
436
437
                    baseline_value = Decimal(0.0) if row_space_periodically[1] is None else row_space_periodically[1]
438
                    reporting[energy_category_id]['timestamps'].append(current_datetime)
439
                    reporting[energy_category_id]['values_baseline'].append(baseline_value)
440
                    reporting[energy_category_id]['subtotal_baseline'] += baseline_value
441
                    reporting[energy_category_id]['subtotal_in_kgce_baseline'] += baseline_value * kgce
442
                    reporting[energy_category_id]['subtotal_in_kgco2e_baseline'] += baseline_value * kgco2e
443
444
                # query reporting period's energy actual
445
                cursor_energy.execute(" SELECT start_datetime_utc, actual_value "
446
                                      " FROM tbl_space_input_category_hourly "
447
                                      " WHERE space_id = %s "
448
                                      "     AND energy_category_id = %s "
449
                                      "     AND start_datetime_utc >= %s "
450
                                      "     AND start_datetime_utc < %s "
451
                                      " ORDER BY start_datetime_utc ",
452
                                      (space['id'],
453
                                       energy_category_id,
454
                                       reporting_start_datetime_utc,
455
                                       reporting_end_datetime_utc))
456
                rows_space_hourly = cursor_energy.fetchall()
457
458
                rows_space_periodically = utilities.aggregate_hourly_data_by_period(rows_space_hourly,
459
                                                                                    reporting_start_datetime_utc,
460
                                                                                    reporting_end_datetime_utc,
461
                                                                                    period_type)
462
                for row_space_periodically in rows_space_periodically:
463
                    current_datetime_local = row_space_periodically[0].replace(tzinfo=timezone.utc) + \
464
                                             timedelta(minutes=timezone_offset)
465
                    if period_type == 'hourly':
466
                        current_datetime = current_datetime_local.strftime('%Y-%m-%dT%H:%M:%S')
467
                    elif period_type == 'daily':
468
                        current_datetime = current_datetime_local.strftime('%Y-%m-%d')
469
                    elif period_type == 'monthly':
470
                        current_datetime = current_datetime_local.strftime('%Y-%m')
471
                    elif period_type == 'yearly':
472
                        current_datetime = current_datetime_local.strftime('%Y')
473
474
                    actual_value = Decimal(0.0) if row_space_periodically[1] is None else row_space_periodically[1]
475
                    reporting[energy_category_id]['values_actual'].append(actual_value)
476
                    reporting[energy_category_id]['subtotal_actual'] += actual_value
477
                    reporting[energy_category_id]['subtotal_in_kgce_actual'] += actual_value * kgce
478
                    reporting[energy_category_id]['subtotal_in_kgco2e_actual'] += actual_value * kgco2e
479
480
                # calculate reporting period's energy savings
481
                for i in range(len(reporting[energy_category_id]['values_baseline'])):
482
                    reporting[energy_category_id]['values_saving'].append(
483
                        reporting[energy_category_id]['values_baseline'][i] -
484
                        reporting[energy_category_id]['values_actual'][i])
485
486
                reporting[energy_category_id]['subtotal_saving'] = \
487
                    reporting[energy_category_id]['subtotal_baseline'] - \
488
                    reporting[energy_category_id]['subtotal_actual']
489
                reporting[energy_category_id]['subtotal_in_kgce_saving'] = \
490
                    reporting[energy_category_id]['subtotal_in_kgce_baseline'] - \
491
                    reporting[energy_category_id]['subtotal_in_kgce_actual']
492
                reporting[energy_category_id]['subtotal_in_kgco2e_saving'] = \
493
                    reporting[energy_category_id]['subtotal_in_kgco2e_baseline'] - \
494
                    reporting[energy_category_id]['subtotal_in_kgco2e_actual']
495
        ################################################################################################################
496
        # Step 9: query tariff data
497
        ################################################################################################################
498
        parameters_data = dict()
499
        parameters_data['names'] = list()
500
        parameters_data['timestamps'] = list()
501
        parameters_data['values'] = list()
502
        if energy_category_set is not None and len(energy_category_set) > 0:
503
            for energy_category_id in energy_category_set:
504
                energy_category_tariff_dict = utilities.get_energy_category_tariffs(space['cost_center_id'],
505
                                                                                    energy_category_id,
506
                                                                                    reporting_start_datetime_utc,
507
                                                                                    reporting_end_datetime_utc)
508
                tariff_timestamp_list = list()
509
                tariff_value_list = list()
510
                for k, v in energy_category_tariff_dict.items():
511
                    # convert k from utc to local
512
                    k = k + timedelta(minutes=timezone_offset)
513
                    tariff_timestamp_list.append(k.isoformat()[0:19][0:19])
514
                    tariff_value_list.append(v)
515
516
                parameters_data['names'].append('TARIFF-' + energy_category_dict[energy_category_id]['name'])
517
                parameters_data['timestamps'].append(tariff_timestamp_list)
518
                parameters_data['values'].append(tariff_value_list)
519
520
        ################################################################################################################
521
        # Step 10: query associated sensors and points data
522
        ################################################################################################################
523
        for point in point_list:
524
            point_values = []
525
            point_timestamps = []
526
            if point['object_type'] == 'ANALOG_VALUE':
527
                query = (" SELECT utc_date_time, actual_value "
528
                         " FROM tbl_analog_value "
529
                         " WHERE point_id = %s "
530
                         "       AND utc_date_time BETWEEN %s AND %s "
531
                         " ORDER BY utc_date_time ")
532
                cursor_historical.execute(query, (point['id'],
533
                                                  reporting_start_datetime_utc,
534
                                                  reporting_end_datetime_utc))
535
                rows = cursor_historical.fetchall()
536
537
                if rows is not None and len(rows) > 0:
538
                    for row in rows:
539
                        current_datetime_local = row[0].replace(tzinfo=timezone.utc) + \
540
                                                 timedelta(minutes=timezone_offset)
541
                        current_datetime = current_datetime_local.strftime('%Y-%m-%dT%H:%M:%S')
542
                        point_timestamps.append(current_datetime)
543
                        point_values.append(row[1])
544
545
            elif point['object_type'] == 'ENERGY_VALUE':
546
                query = (" SELECT utc_date_time, actual_value "
547
                         " FROM tbl_energy_value "
548
                         " WHERE point_id = %s "
549
                         "       AND utc_date_time BETWEEN %s AND %s "
550
                         " ORDER BY utc_date_time ")
551
                cursor_historical.execute(query, (point['id'],
552
                                                  reporting_start_datetime_utc,
553
                                                  reporting_end_datetime_utc))
554
                rows = cursor_historical.fetchall()
555
556
                if rows is not None and len(rows) > 0:
557
                    for row in rows:
558
                        current_datetime_local = row[0].replace(tzinfo=timezone.utc) + \
559
                                                 timedelta(minutes=timezone_offset)
560
                        current_datetime = current_datetime_local.strftime('%Y-%m-%dT%H:%M:%S')
561
                        point_timestamps.append(current_datetime)
562
                        point_values.append(row[1])
563
            elif point['object_type'] == 'DIGITAL_VALUE':
564
                query = (" SELECT utc_date_time, actual_value "
565
                         " FROM tbl_digital_value "
566
                         " WHERE point_id = %s "
567
                         "       AND utc_date_time BETWEEN %s AND %s ")
568
                cursor_historical.execute(query, (point['id'],
569
                                                  reporting_start_datetime_utc,
570
                                                  reporting_end_datetime_utc))
571
                rows = cursor_historical.fetchall()
572
573
                if rows is not None and len(rows) > 0:
574
                    for row in rows:
575
                        current_datetime_local = row[0].replace(tzinfo=timezone.utc) + \
576
                                                 timedelta(minutes=timezone_offset)
577
                        current_datetime = current_datetime_local.strftime('%Y-%m-%dT%H:%M:%S')
578
                        point_timestamps.append(current_datetime)
579
                        point_values.append(row[1])
580
581
            parameters_data['names'].append(point['name'] + ' (' + point['units'] + ')')
582
            parameters_data['timestamps'].append(point_timestamps)
583
            parameters_data['values'].append(point_values)
584
585
        ################################################################################################################
586
        # Step 11: query child spaces energy saving
587
        ################################################################################################################
588
        child_space_data = dict()
589
590
        if energy_category_set is not None and len(energy_category_set) > 0:
591
            for energy_category_id in energy_category_set:
592
                child_space_data[energy_category_id] = dict()
593
                child_space_data[energy_category_id]['child_space_names'] = list()
594
                child_space_data[energy_category_id]['subtotals_saving'] = list()
595
                child_space_data[energy_category_id]['subtotals_in_kgce_saving'] = list()
596
                child_space_data[energy_category_id]['subtotals_in_kgco2e_saving'] = list()
597
                kgce = energy_category_dict[energy_category_id]['kgce']
598
                kgco2e = energy_category_dict[energy_category_id]['kgco2e']
599
                for child_space in child_space_list:
600
                    child_space_data[energy_category_id]['child_space_names'].append(child_space['name'])
601
                    # query child space's energy baseline
602
                    cursor_energy_baseline.execute(" SELECT SUM(actual_value) "
603
                                                   " FROM tbl_space_input_category_hourly "
604
                                                   " WHERE space_id = %s "
605
                                                   "     AND energy_category_id = %s "
606
                                                   "     AND start_datetime_utc >= %s "
607
                                                   "     AND start_datetime_utc < %s "
608
                                                   " ORDER BY start_datetime_utc ",
609
                                                   (child_space['id'],
610
                                                    energy_category_id,
611
                                                    reporting_start_datetime_utc,
612
                                                    reporting_end_datetime_utc))
613
                    row_subtotal = cursor_energy_baseline.fetchone()
614
615
                    subtotal = Decimal(0.0) if (row_subtotal is None or row_subtotal[0] is None) else row_subtotal[0]
616
                    subtotal_baseline = subtotal
617
                    subtotal_in_kgce_baseline = subtotal * kgce
618
                    subtotal_in_kgco2e_baseline = subtotal * kgco2e
619
                    # query child space's energy actual
620
                    cursor_energy.execute(" SELECT SUM(actual_value) "
621
                                          " FROM tbl_space_input_category_hourly "
622
                                          " WHERE space_id = %s "
623
                                          "     AND energy_category_id = %s "
624
                                          "     AND start_datetime_utc >= %s "
625
                                          "     AND start_datetime_utc < %s "
626
                                          " ORDER BY start_datetime_utc ",
627
                                          (child_space['id'],
628
                                           energy_category_id,
629
                                           reporting_start_datetime_utc,
630
                                           reporting_end_datetime_utc))
631
                    row_subtotal = cursor_energy.fetchone()
632
633
                    subtotal = Decimal(0.0) if (row_subtotal is None or row_subtotal[0] is None) else row_subtotal[0]
634
                    subtotal_actual = subtotal
635
                    subtotal_in_kgce_actual = subtotal * kgce
636
                    subtotal_in_kgco2e_actual = subtotal * kgco2e
637
638
                    # calculate child space's energy saving
639
                    child_space_data[energy_category_id]['subtotals_saving'].append(
640
                        subtotal_baseline - subtotal_actual)
641
                    child_space_data[energy_category_id]['subtotals_in_kgce_saving'].append(
642
                        subtotal_in_kgce_baseline - subtotal_in_kgce_actual)
643
                    child_space_data[energy_category_id]['subtotals_in_kgco2e_saving'].append(
644
                        subtotal_in_kgco2e_baseline - subtotal_in_kgco2e_actual)
645
        ################################################################################################################
646
        # Step 12: construct the report
647
        ################################################################################################################
648
        if cursor_system:
649
            cursor_system.close()
650
        if cnx_system:
651
            cnx_system.disconnect()
652
653
        if cursor_energy:
654
            cursor_energy.close()
655
        if cnx_energy:
656
            cnx_energy.disconnect()
657
658
        if cursor_energy_baseline:
659
            cursor_energy_baseline.close()
660
        if cnx_energy_baseline:
661
            cnx_energy_baseline.disconnect()
662
663
        result = dict()
664
665
        result['space'] = dict()
666
        result['space']['name'] = space['name']
667
        result['space']['area'] = space['area']
668
669
        result['base_period'] = dict()
670
        result['base_period']['names'] = list()
671
        result['base_period']['units'] = list()
672
        result['base_period']['timestamps'] = list()
673
        result['base_period']['values_saving'] = list()
674
        result['base_period']['subtotals_saving'] = list()
675
        result['base_period']['subtotals_in_kgce_saving'] = list()
676
        result['base_period']['subtotals_in_kgco2e_saving'] = list()
677
        result['base_period']['total_in_kgce_saving'] = Decimal(0.0)
678
        result['base_period']['total_in_kgco2e_saving'] = Decimal(0.0)
679
        if energy_category_set is not None and len(energy_category_set) > 0:
680
            for energy_category_id in energy_category_set:
681
                result['base_period']['names'].append(energy_category_dict[energy_category_id]['name'])
682
                result['base_period']['units'].append(energy_category_dict[energy_category_id]['unit_of_measure'])
683
                result['base_period']['timestamps'].append(base[energy_category_id]['timestamps'])
684
                result['base_period']['values_saving'].append(base[energy_category_id]['values_saving'])
685
                result['base_period']['subtotals_saving'].append(base[energy_category_id]['subtotal_saving'])
686
                result['base_period']['subtotals_in_kgce_saving'].append(
687
                    base[energy_category_id]['subtotal_in_kgce_saving'])
688
                result['base_period']['subtotals_in_kgco2e_saving'].append(
689
                    base[energy_category_id]['subtotal_in_kgco2e_saving'])
690
                result['base_period']['total_in_kgce_saving'] += base[energy_category_id]['subtotal_in_kgce_saving']
691
                result['base_period']['total_in_kgco2e_saving'] += base[energy_category_id]['subtotal_in_kgco2e_saving']
692
693
        result['reporting_period'] = dict()
694
        result['reporting_period']['names'] = list()
695
        result['reporting_period']['energy_category_ids'] = list()
696
        result['reporting_period']['units'] = list()
697
        result['reporting_period']['timestamps'] = list()
698
        result['reporting_period']['values_saving'] = list()
699
        result['reporting_period']['subtotals_saving'] = list()
700
        result['reporting_period']['subtotals_in_kgce_saving'] = list()
701
        result['reporting_period']['subtotals_in_kgco2e_saving'] = list()
702
        result['reporting_period']['subtotals_per_unit_area_saving'] = list()
703
        result['reporting_period']['increment_rates_saving'] = list()
704
        result['reporting_period']['total_in_kgce_saving'] = Decimal(0.0)
705
        result['reporting_period']['total_in_kgco2e_saving'] = Decimal(0.0)
706
        result['reporting_period']['increment_rate_in_kgce_saving'] = Decimal(0.0)
707
        result['reporting_period']['increment_rate_in_kgco2e_saving'] = Decimal(0.0)
708
709
        if energy_category_set is not None and len(energy_category_set) > 0:
710
            for energy_category_id in energy_category_set:
711
                result['reporting_period']['names'].append(energy_category_dict[energy_category_id]['name'])
712
                result['reporting_period']['energy_category_ids'].append(energy_category_id)
713
                result['reporting_period']['units'].append(energy_category_dict[energy_category_id]['unit_of_measure'])
714
                result['reporting_period']['timestamps'].append(reporting[energy_category_id]['timestamps'])
715
                result['reporting_period']['values_saving'].append(reporting[energy_category_id]['values_saving'])
716
                result['reporting_period']['subtotals_saving'].append(reporting[energy_category_id]['subtotal_saving'])
717
                result['reporting_period']['subtotals_in_kgce_saving'].append(
718
                    reporting[energy_category_id]['subtotal_in_kgce_saving'])
719
                result['reporting_period']['subtotals_in_kgco2e_saving'].append(
720
                    reporting[energy_category_id]['subtotal_in_kgco2e_saving'])
721
                result['reporting_period']['subtotals_per_unit_area_saving'].append(
722
                    reporting[energy_category_id]['subtotal_saving'] / space['area'] if space['area'] > 0.0 else None)
723
                result['reporting_period']['increment_rates_saving'].append(
724
                    (reporting[energy_category_id]['subtotal_saving'] - base[energy_category_id]['subtotal_saving']) /
725
                    base[energy_category_id]['subtotal_saving']
726
                    if base[energy_category_id]['subtotal_saving'] > 0.0 else None)
727
                result['reporting_period']['total_in_kgce_saving'] += \
728
                    reporting[energy_category_id]['subtotal_in_kgce_saving']
729
                result['reporting_period']['total_in_kgco2e_saving'] += \
730
                    reporting[energy_category_id]['subtotal_in_kgco2e_saving']
731
732
        result['reporting_period']['total_in_kgco2e_per_unit_area_saving'] = \
733
            result['reporting_period']['total_in_kgce_saving'] / space['area'] if space['area'] > 0.0 else None
734
735
        result['reporting_period']['increment_rate_in_kgce_saving'] = \
736
            (result['reporting_period']['total_in_kgce_saving'] - result['base_period']['total_in_kgce_saving']) / \
737
            result['base_period']['total_in_kgce_saving'] \
738
            if result['base_period']['total_in_kgce_saving'] > Decimal(0.0) else None
739
740
        result['reporting_period']['total_in_kgce_per_unit_area_saving'] = \
741
            result['reporting_period']['total_in_kgco2e_saving'] / space['area'] if space['area'] > 0.0 else None
742
743
        result['reporting_period']['increment_rate_in_kgco2e_saving'] = \
744
            (result['reporting_period']['total_in_kgco2e_saving'] - result['base_period']['total_in_kgco2e_saving']) / \
745
            result['base_period']['total_in_kgco2e_saving'] \
746
            if result['base_period']['total_in_kgco2e_saving'] > Decimal(0.0) else None
747
748
        result['parameters'] = {
749
            "names": parameters_data['names'],
750
            "timestamps": parameters_data['timestamps'],
751
            "values": parameters_data['values']
752
        }
753
754
        result['child_space'] = dict()
755
        result['child_space']['energy_category_names'] = list()  # 1D array [energy category]
756
        result['child_space']['units'] = list()  # 1D array [energy category]
757
        result['child_space']['child_space_names_array'] = list()  # 2D array [energy category][child space]
758
        result['child_space']['subtotals_saving_array'] = list()  # 2D array [energy category][child space]
759
        result['child_space']['subtotals_in_kgce_saving_array'] = list()  # 2D array [energy category][child space]
760
        result['child_space']['subtotals_in_kgco2e_saving_array'] = list()  # 2D array [energy category][child space]
761 View Code Duplication
        if energy_category_set is not None and len(energy_category_set) > 0:
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
762
            for energy_category_id in energy_category_set:
763
                result['child_space']['energy_category_names'].append(energy_category_dict[energy_category_id]['name'])
764
                result['child_space']['units'].append(energy_category_dict[energy_category_id]['unit_of_measure'])
765
                result['child_space']['child_space_names_array'].append(
766
                    child_space_data[energy_category_id]['child_space_names'])
767
                result['child_space']['subtotals_saving_array'].append(
768
                    child_space_data[energy_category_id]['subtotals_saving'])
769
                result['child_space']['subtotals_in_kgce_saving_array'].append(
770
                    child_space_data[energy_category_id]['subtotals_in_kgce_saving'])
771
                result['child_space']['subtotals_in_kgco2e_saving_array'].append(
772
                    child_space_data[energy_category_id]['subtotals_in_kgco2e_saving'])
773
774
        resp.body = json.dumps(result)
775