1 | import re |
||
2 | from datetime import datetime, timedelta, timezone |
||
3 | from decimal import Decimal |
||
4 | import falcon |
||
5 | import mysql.connector |
||
6 | import simplejson as json |
||
7 | from core.useractivity import access_control, api_key_control |
||
8 | import config |
||
9 | |||
10 | |||
11 | class Reporting: |
||
12 | def __init__(self): |
||
13 | """Initializes Class""" |
||
14 | pass |
||
15 | |||
16 | @staticmethod |
||
17 | def on_options(req, resp): |
||
18 | _ = req |
||
19 | resp.status = falcon.HTTP_200 |
||
20 | |||
21 | #################################################################################################################### |
||
22 | # PROCEDURES |
||
23 | # Step 1: valid parameters |
||
24 | # Step 2: query the microgrid |
||
25 | # Step 3: query associated batteries |
||
26 | # Step 4: query associated power conversion systems |
||
27 | # Step 5: query associated evchargers |
||
28 | # Step 6: query associated generators |
||
29 | # Step 7: query associated grids |
||
30 | # Step 8: query associated heatpumps |
||
31 | # Step 9: query associated loads |
||
32 | # Step 10: query associated photovoltaics |
||
33 | # Step 11: query associated schedules |
||
34 | # Step 12: query associated sensors |
||
35 | # Step 13: query associated meters data |
||
36 | # Step 14: query associated points data |
||
37 | # Step 15: construct the report |
||
38 | #################################################################################################################### |
||
39 | @staticmethod |
||
40 | def on_get(req, resp): |
||
41 | if 'API-KEY' not in req.headers or \ |
||
42 | not isinstance(req.headers['API-KEY'], str) or \ |
||
43 | len(str.strip(req.headers['API-KEY'])) == 0: |
||
44 | access_control(req) |
||
45 | else: |
||
46 | api_key_control(req) |
||
47 | print(req.params) |
||
48 | # this procedure accepts microgrid id or microgrid uuid to identify a microgrid |
||
49 | microgrid_id = req.params.get('id') |
||
50 | microgrid_uuid = req.params.get('uuid') |
||
51 | |||
52 | ################################################################################################################ |
||
53 | # Step 1: valid parameters |
||
54 | ################################################################################################################ |
||
55 | if microgrid_id is None and microgrid_uuid is None: |
||
56 | raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST', |
||
57 | description='API.INVALID_MICROGRID_ID') |
||
58 | |||
59 | if microgrid_id is not None: |
||
60 | microgrid_id = str.strip(microgrid_id) |
||
61 | if not microgrid_id.isdigit() or int(microgrid_id) <= 0: |
||
62 | raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST', |
||
63 | description='API.INVALID_MICROGRID_ID') |
||
64 | |||
65 | if microgrid_uuid is not None: |
||
66 | regex = re.compile(r'^[a-f0-9]{8}-?[a-f0-9]{4}-?4[a-f0-9]{3}-?[89ab][a-f0-9]{3}-?[a-f0-9]{12}\Z', re.I) |
||
67 | match = regex.match(str.strip(microgrid_uuid)) |
||
68 | if not bool(match): |
||
69 | raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST', |
||
70 | description='API.INVALID_MICROGRID_UUID') |
||
71 | |||
72 | reporting_start_datetime_utc = datetime.utcnow() - timedelta(days=3) |
||
73 | reporting_end_datetime_utc = datetime.utcnow() |
||
74 | |||
75 | ################################################################################################################ |
||
76 | # Step 2: Step 2: query the microgrid |
||
77 | ################################################################################################################ |
||
78 | cnx_system = mysql.connector.connect(**config.myems_system_db) |
||
79 | cursor_system = cnx_system.cursor() |
||
80 | |||
81 | cnx_energy = mysql.connector.connect(**config.myems_energy_db) |
||
82 | cursor_energy = cnx_energy.cursor() |
||
83 | |||
84 | cnx_billing = mysql.connector.connect(**config.myems_billing_db) |
||
85 | cursor_billing = cnx_billing.cursor() |
||
86 | |||
87 | cnx_carbon = mysql.connector.connect(**config.myems_carbon_db) |
||
88 | cursor_carbon = cnx_carbon.cursor() |
||
89 | |||
90 | cnx_historical = mysql.connector.connect(**config.myems_historical_db) |
||
91 | cursor_historical = cnx_historical.cursor() |
||
92 | |||
93 | query = (" SELECT id, name, uuid " |
||
94 | " FROM tbl_contacts ") |
||
95 | cursor_system.execute(query) |
||
96 | rows_contacts = cursor_system.fetchall() |
||
97 | |||
98 | contact_dict = dict() |
||
99 | if rows_contacts is not None and len(rows_contacts) > 0: |
||
100 | for row in rows_contacts: |
||
101 | contact_dict[row[0]] = {"id": row[0], |
||
102 | "name": row[1], |
||
103 | "uuid": row[2]} |
||
104 | |||
105 | query = (" SELECT id, name, uuid " |
||
106 | " FROM tbl_cost_centers ") |
||
107 | cursor_system.execute(query) |
||
108 | rows_cost_centers = cursor_system.fetchall() |
||
109 | |||
110 | cost_center_dict = dict() |
||
111 | if rows_cost_centers is not None and len(rows_cost_centers) > 0: |
||
112 | for row in rows_cost_centers: |
||
113 | cost_center_dict[row[0]] = {"id": row[0], |
||
114 | "name": row[1], |
||
115 | "uuid": row[2]} |
||
116 | if microgrid_id is not None: |
||
117 | query = (" SELECT m.id, m.name, m.uuid, " |
||
118 | " m.address, m.postal_code, m.latitude, m.longitude, m.rated_capacity, m.rated_power, " |
||
119 | " m.contact_id, m.cost_center_id, m.serial_number, s.source_code, m.description " |
||
120 | " FROM tbl_microgrids m, tbl_svgs s" |
||
121 | " WHERE m.svg_id = s.id AND m.id = %s ") |
||
122 | cursor_system.execute(query, (microgrid_id,)) |
||
123 | row = cursor_system.fetchone() |
||
124 | elif microgrid_uuid is not None: |
||
125 | query = (" SELECT m.id, m.name, m.uuid, " |
||
126 | " m.address, m.postal_code, m.latitude, m.longitude, m.rated_capacity, m.rated_power, " |
||
127 | " m.contact_id, m.cost_center_id, m.serial_number, s.source_code, m.description " |
||
128 | " FROM tbl_microgrids m, tbl_svgs s " |
||
129 | " WHERE m.svg_id = s.id AND m.uuid = %s ") |
||
130 | cursor_system.execute(query, (microgrid_uuid,)) |
||
131 | row = cursor_system.fetchone() |
||
132 | |||
133 | if row is None: |
||
0 ignored issues
–
show
introduced
by
![]() |
|||
134 | cursor_system.close() |
||
135 | cnx_system.close() |
||
136 | raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND', |
||
137 | description='API.MICROGRID_NOT_FOUND') |
||
138 | else: |
||
139 | microgrid_id = row[0] |
||
140 | meta_result = {"id": row[0], |
||
141 | "name": row[1], |
||
142 | "uuid": row[2], |
||
143 | "address": row[3], |
||
144 | "postal_code": row[4], |
||
145 | "latitude": row[5], |
||
146 | "longitude": row[6], |
||
147 | "rated_capacity": row[7], |
||
148 | "rated_power": row[8], |
||
149 | "contact": contact_dict.get(row[9], None), |
||
150 | "cost_center": cost_center_dict.get(row[10], None), |
||
151 | "serial_number": row[11], |
||
152 | "svg": row[12], |
||
153 | "description": row[13], |
||
154 | "qrcode": 'microgrid:' + row[2]} |
||
155 | |||
156 | point_list = list() |
||
157 | meter_list = list() |
||
158 | |||
159 | # query all energy categories in system |
||
160 | cursor_system.execute(" SELECT id, name, unit_of_measure, kgce, kgco2e " |
||
161 | " FROM tbl_energy_categories " |
||
162 | " ORDER BY id ", ) |
||
163 | rows_energy_categories = cursor_system.fetchall() |
||
164 | if rows_energy_categories is None or len(rows_energy_categories) == 0: |
||
165 | if cursor_system: |
||
166 | cursor_system.close() |
||
167 | if cnx_system: |
||
168 | cnx_system.close() |
||
169 | raise falcon.HTTPError(status=falcon.HTTP_404, |
||
170 | title='API.NOT_FOUND', |
||
171 | description='API.ENERGY_CATEGORY_NOT_FOUND') |
||
172 | energy_category_dict = dict() |
||
173 | for row_energy_category in rows_energy_categories: |
||
174 | energy_category_dict[row_energy_category[0]] = {"name": row_energy_category[1], |
||
175 | "unit_of_measure": row_energy_category[2], |
||
176 | "kgce": row_energy_category[3], |
||
177 | "kgco2e": row_energy_category[4]} |
||
178 | |||
179 | ################################################################################################################ |
||
180 | # Step 3: query associated batteries |
||
181 | ################################################################################################################ |
||
182 | |||
183 | energy_value_latest_dict = dict() |
||
184 | query = (" SELECT point_id, actual_value " |
||
185 | " FROM tbl_energy_value_latest ") |
||
186 | cursor_historical.execute(query, ) |
||
187 | energy_value_latest_rows = cursor_historical.fetchall() |
||
188 | for row in energy_value_latest_rows: |
||
189 | energy_value_latest_dict[row[0]] = row[1] |
||
190 | |||
191 | analog_value_latest_dict = dict() |
||
192 | query = (" SELECT point_id, actual_value " |
||
193 | " FROM tbl_analog_value_latest ") |
||
194 | cursor_historical.execute(query, ) |
||
195 | analog_value_latest_rows = cursor_historical.fetchall() |
||
196 | for row in analog_value_latest_rows: |
||
197 | analog_value_latest_dict[row[0]] = row[1] |
||
198 | |||
199 | digital_value_latest_dict = dict() |
||
200 | query = (" SELECT point_id, actual_value " |
||
201 | " FROM tbl_digital_value_latest ") |
||
202 | cursor_historical.execute(query, ) |
||
203 | digital_value_latest_rows = cursor_historical.fetchall() |
||
204 | for row in digital_value_latest_rows: |
||
205 | digital_value_latest_dict[row[0]] = row[1] |
||
206 | |||
207 | cursor_system.execute(" SELECT battery_state_point_id " |
||
208 | " FROM tbl_microgrids_batteries " |
||
209 | " WHERE microgrid_id = %s " |
||
210 | " ORDER BY id " |
||
211 | " LIMIT 1 ", |
||
212 | (microgrid_id,)) |
||
213 | row_point = cursor_system.fetchone() |
||
214 | if row_point is not None: |
||
215 | battery_state_point_id = row_point[0] |
||
216 | |||
217 | if digital_value_latest_dict.get(battery_state_point_id) is not None: |
||
0 ignored issues
–
show
|
|||
218 | battery_state_point_value = digital_value_latest_dict.get(battery_state_point_id) |
||
219 | |||
220 | cursor_system.execute(" SELECT p.id, mb.name, p.units, p.object_type " |
||
221 | " FROM tbl_microgrids_batteries mb, tbl_points p " |
||
222 | " WHERE mb.microgrid_id = %s AND mb.soc_point_id = p.id ", |
||
223 | (microgrid_id,)) |
||
224 | row_point = cursor_system.fetchone() |
||
225 | if row_point is not None: |
||
226 | point_list.append({"id": row_point[0], |
||
227 | "name": row_point[1] + '.SOC', |
||
228 | "units": row_point[2], |
||
229 | "object_type": row_point[3]}) |
||
230 | |||
231 | cursor_system.execute(" SELECT p.id, mb.name, p.units, p.object_type " |
||
232 | " FROM tbl_microgrids_batteries mb, tbl_points p " |
||
233 | " WHERE mb.microgrid_id = %s AND mb.power_point_id = p.id ", |
||
234 | (microgrid_id,)) |
||
235 | row_point = cursor_system.fetchone() |
||
236 | if row_point is not None: |
||
237 | point_list.append({"id": row_point[0], |
||
238 | "name": row_point[1]+'.P', |
||
239 | "units": row_point[2], |
||
240 | "object_type": row_point[3]}) |
||
241 | charge_meter_id = None |
||
242 | cursor_system.execute(" SELECT m.id, mb.name, m.energy_category_id " |
||
243 | " FROM tbl_microgrids_batteries mb, tbl_meters m " |
||
244 | " WHERE mb.microgrid_id = %s AND mb.charge_meter_id = m.id ", |
||
245 | (microgrid_id,)) |
||
246 | row_meter = cursor_system.fetchone() |
||
247 | if row_meter is not None: |
||
248 | meter_list.append({"id": row_meter[0], |
||
249 | "name": row_meter[1] + '.Charge', |
||
250 | "energy_category_id": row_meter[2]}) |
||
251 | charge_meter_id = row_meter[0] |
||
252 | |||
253 | discharge_meter_id = None |
||
254 | cursor_system.execute(" SELECT m.id, mb.name, m.energy_category_id " |
||
255 | " FROM tbl_microgrids_batteries mb, tbl_meters m " |
||
256 | " WHERE mb.microgrid_id = %s AND mb.discharge_meter_id = m.id ", |
||
257 | (microgrid_id,)) |
||
258 | row_meter = cursor_system.fetchone() |
||
259 | if row_meter is not None: |
||
260 | meter_list.append({"id": row_meter[0], |
||
261 | "name": row_meter[1] + '.Discharge', |
||
262 | "energy_category_id": row_meter[2]}) |
||
263 | discharge_meter_id = row_meter[0] |
||
264 | |||
265 | ################################################################################################################ |
||
266 | # Step 4: query associated power conversion systems |
||
267 | ################################################################################################################ |
||
268 | # Step 4.1 query energy indicator data |
||
269 | timezone_offset = int(config.utc_offset[1:3]) * 60 + int(config.utc_offset[4:6]) |
||
270 | if config.utc_offset[0] == '-': |
||
271 | timezone_offset = -timezone_offset |
||
272 | |||
273 | today_end_datetime_utc = datetime.utcnow() |
||
274 | today_end_datetime_local = datetime.utcnow() + timedelta(minutes=timezone_offset) |
||
275 | today_start_datetime_local = today_end_datetime_local.replace(hour=0, minute=0, second=0, microsecond=0) |
||
276 | today_start_datetime_utc = today_start_datetime_local - timedelta(minutes=timezone_offset) |
||
277 | |||
278 | today_charge_energy_value = Decimal(0.0) |
||
279 | today_discharge_energy_value = Decimal(0.0) |
||
280 | total_charge_energy_value = Decimal(0.0) |
||
281 | total_discharge_energy_value = Decimal(0.0) |
||
282 | |||
283 | # query meter energy |
||
284 | cursor_energy.execute(" SELECT SUM(actual_value) " |
||
285 | " FROM tbl_meter_hourly " |
||
286 | " WHERE meter_id = %s " |
||
287 | " AND start_datetime_utc >= %s " |
||
288 | " AND start_datetime_utc < %s ", |
||
289 | (charge_meter_id, |
||
290 | today_start_datetime_utc, |
||
291 | today_end_datetime_utc)) |
||
292 | row = cursor_energy.fetchone() |
||
293 | if row is not None: |
||
294 | today_charge_energy_value = row[0] |
||
295 | |||
296 | cursor_energy.execute(" SELECT SUM(actual_value) " |
||
297 | " FROM tbl_meter_hourly " |
||
298 | " WHERE meter_id = %s " |
||
299 | " AND start_datetime_utc >= %s " |
||
300 | " AND start_datetime_utc < %s ", |
||
301 | (discharge_meter_id, |
||
302 | today_start_datetime_utc, |
||
303 | today_end_datetime_utc)) |
||
304 | row = cursor_energy.fetchone() |
||
305 | if row is not None: |
||
306 | today_discharge_energy_value = row[0] |
||
307 | |||
308 | cursor_energy.execute(" SELECT SUM(actual_value) " |
||
309 | " FROM tbl_meter_hourly " |
||
310 | " WHERE meter_id = %s ", |
||
311 | (charge_meter_id,)) |
||
312 | row = cursor_energy.fetchone() |
||
313 | if row is not None: |
||
314 | total_charge_energy_value = row[0] |
||
315 | |||
316 | cursor_energy.execute(" SELECT SUM(actual_value) " |
||
317 | " FROM tbl_meter_hourly " |
||
318 | " WHERE meter_id = %s ", |
||
319 | (discharge_meter_id,)) |
||
320 | row = cursor_energy.fetchone() |
||
321 | if row is not None: |
||
322 | total_discharge_energy_value = row[0] |
||
323 | |||
324 | # Step 4.2 query revenue indicator data |
||
325 | today_charge_revenue_value = Decimal(0.0) |
||
326 | today_discharge_revenue_value = Decimal(0.0) |
||
327 | total_charge_revenue_value = Decimal(0.0) |
||
328 | total_discharge_revenue_value = Decimal(0.0) |
||
329 | |||
330 | # query meter revenue |
||
331 | cursor_billing.execute(" SELECT SUM(actual_value) " |
||
332 | " FROM tbl_meter_hourly " |
||
333 | " WHERE meter_id = %s " |
||
334 | " AND start_datetime_utc >= %s " |
||
335 | " AND start_datetime_utc < %s ", |
||
336 | (charge_meter_id, |
||
337 | today_start_datetime_utc, |
||
338 | today_end_datetime_utc)) |
||
339 | row = cursor_billing.fetchone() |
||
340 | if row is not None: |
||
341 | today_charge_revenue_value = row[0] |
||
342 | |||
343 | cursor_billing.execute(" SELECT SUM(actual_value) " |
||
344 | " FROM tbl_meter_hourly " |
||
345 | " WHERE meter_id = %s " |
||
346 | " AND start_datetime_utc >= %s " |
||
347 | " AND start_datetime_utc < %s ", |
||
348 | (discharge_meter_id, |
||
349 | today_start_datetime_utc, |
||
350 | today_end_datetime_utc)) |
||
351 | row = cursor_billing.fetchone() |
||
352 | if row is not None: |
||
353 | today_discharge_revenue_value = row[0] |
||
354 | |||
355 | cursor_billing.execute(" SELECT SUM(actual_value) " |
||
356 | " FROM tbl_meter_hourly " |
||
357 | " WHERE meter_id = %s ", |
||
358 | (charge_meter_id,)) |
||
359 | row = cursor_billing.fetchone() |
||
360 | if row is not None: |
||
361 | total_charge_revenue_value = row[0] |
||
362 | |||
363 | cursor_billing.execute(" SELECT SUM(actual_value) " |
||
364 | " FROM tbl_meter_hourly " |
||
365 | " WHERE meter_id = %s ", |
||
366 | (discharge_meter_id,)) |
||
367 | row = cursor_billing.fetchone() |
||
368 | if row is not None: |
||
369 | total_discharge_revenue_value = row[0] |
||
370 | |||
371 | # Step 4.3 query carbon indicator data |
||
372 | today_charge_carbon_value = Decimal(0.0) |
||
373 | today_discharge_carbon_value = Decimal(0.0) |
||
374 | total_charge_carbon_value = Decimal(0.0) |
||
375 | total_discharge_carbon_value = Decimal(0.0) |
||
376 | |||
377 | # query meter carbon |
||
378 | cursor_carbon.execute(" SELECT SUM(actual_value) " |
||
379 | " FROM tbl_meter_hourly " |
||
380 | " WHERE meter_id = %s " |
||
381 | " AND start_datetime_utc >= %s " |
||
382 | " AND start_datetime_utc < %s ", |
||
383 | (charge_meter_id, |
||
384 | today_start_datetime_utc, |
||
385 | today_end_datetime_utc)) |
||
386 | row = cursor_carbon.fetchone() |
||
387 | if row is not None: |
||
388 | today_charge_carbon_value = row[0] |
||
389 | |||
390 | cursor_carbon.execute(" SELECT SUM(actual_value) " |
||
391 | " FROM tbl_meter_hourly " |
||
392 | " WHERE meter_id = %s " |
||
393 | " AND start_datetime_utc >= %s " |
||
394 | " AND start_datetime_utc < %s ", |
||
395 | (discharge_meter_id, |
||
396 | today_start_datetime_utc, |
||
397 | today_end_datetime_utc)) |
||
398 | row = cursor_carbon.fetchone() |
||
399 | if row is not None: |
||
400 | today_discharge_carbon_value = row[0] |
||
401 | |||
402 | cursor_carbon.execute(" SELECT SUM(actual_value) " |
||
403 | " FROM tbl_meter_hourly " |
||
404 | " WHERE meter_id = %s ", |
||
405 | (charge_meter_id,)) |
||
406 | row = cursor_carbon.fetchone() |
||
407 | if row is not None: |
||
408 | total_charge_carbon_value = row[0] |
||
409 | |||
410 | cursor_carbon.execute(" SELECT SUM(actual_value) " |
||
411 | " FROM tbl_meter_hourly " |
||
412 | " WHERE meter_id = %s ", |
||
413 | (discharge_meter_id,)) |
||
414 | row = cursor_carbon.fetchone() |
||
415 | if row is not None: |
||
416 | total_discharge_carbon_value = row[0] |
||
417 | |||
418 | ################################################################################################################ |
||
419 | # Step 5: query associated evchargers |
||
420 | ################################################################################################################ |
||
421 | cursor_system.execute(" SELECT p.id, me.name, p.units, p.object_type " |
||
422 | " FROM tbl_microgrids_evchargers me, tbl_points p " |
||
423 | " WHERE me.microgrid_id = %s AND me.power_point_id = p.id ", |
||
424 | (microgrid_id,)) |
||
425 | rows_points = cursor_system.fetchall() |
||
426 | if rows_points is not None and len(rows_points) > 0: |
||
427 | for row_point in rows_points: |
||
428 | point_list.append({"id": row_point[0], |
||
429 | "name": row_point[1]+'.P', |
||
430 | "units": row_point[2], |
||
431 | "object_type": row_point[3]}) |
||
432 | |||
433 | cursor_system.execute(" SELECT m.id, me.name, m.energy_category_id " |
||
434 | " FROM tbl_microgrids_evchargers me, tbl_meters m " |
||
435 | " WHERE me.microgrid_id = %s AND me.meter_id = m.id ", |
||
436 | (microgrid_id,)) |
||
437 | rows_meters = cursor_system.fetchall() |
||
438 | if rows_meters is not None and len(rows_meters) > 0: |
||
439 | for row_meter in rows_meters: |
||
440 | meter_list.append({"id": row_meter[0], |
||
441 | "name": row_meter[1], |
||
442 | "energy_category_id": row_meter[2]}) |
||
443 | ################################################################################################################ |
||
444 | # Step 6: query associated generators |
||
445 | ################################################################################################################ |
||
446 | cursor_system.execute(" SELECT p.id, mg.name, p.units, p.object_type " |
||
447 | " FROM tbl_microgrids_generators mg, tbl_points p " |
||
448 | " WHERE mg.microgrid_id = %s AND mg.power_point_id = p.id ", |
||
449 | (microgrid_id,)) |
||
450 | row_point = cursor_system.fetchone() |
||
451 | if row_point is not None: |
||
452 | point_list.append({"id": row_point[0], |
||
453 | "name": row_point[1]+'.P', |
||
454 | "units": row_point[2], |
||
455 | "object_type": row_point[3]}) |
||
456 | |||
457 | cursor_system.execute(" SELECT m.id, mg.name, m.energy_category_id " |
||
458 | " FROM tbl_microgrids_generators mg, tbl_meters m " |
||
459 | " WHERE mg.microgrid_id = %s AND mg.meter_id = m.id ", |
||
460 | (microgrid_id,)) |
||
461 | row_meter = cursor_system.fetchone() |
||
462 | if row_meter is not None: |
||
463 | meter_list.append({"id": row_meter[0], |
||
464 | "name": row_meter[1], |
||
465 | "energy_category_id": row_meter[2]}) |
||
466 | ################################################################################################################ |
||
467 | # Step 7: query associated grids |
||
468 | ################################################################################################################ |
||
469 | cursor_system.execute(" SELECT p.id, mg.name, p.units, p.object_type " |
||
470 | " FROM tbl_microgrids_grids mg, tbl_points p " |
||
471 | " WHERE mg.microgrid_id = %s AND mg.power_point_id = p.id ", |
||
472 | (microgrid_id,)) |
||
473 | row_point = cursor_system.fetchone() |
||
474 | if row_point is not None: |
||
475 | point_list.append({"id": row_point[0], |
||
476 | "name": row_point[1]+'.P', |
||
477 | "units": row_point[2], |
||
478 | "object_type": row_point[3]}) |
||
479 | |||
480 | cursor_system.execute(" SELECT m.id, mg.name, m.energy_category_id " |
||
481 | " FROM tbl_microgrids_grids mg, tbl_meters m " |
||
482 | " WHERE mg.microgrid_id = %s AND mg.buy_meter_id = m.id ", |
||
483 | (microgrid_id,)) |
||
484 | row_meter = cursor_system.fetchone() |
||
485 | if row_meter is not None: |
||
486 | meter_list.append({"id": row_meter[0], |
||
487 | "name": row_meter[1] + '.Buy', |
||
488 | "energy_category_id": row_meter[2]}) |
||
489 | |||
490 | cursor_system.execute(" SELECT m.id, mg.name, m.energy_category_id " |
||
491 | " FROM tbl_microgrids_grids mg, tbl_meters m " |
||
492 | " WHERE mg.microgrid_id = %s AND mg.sell_meter_id = m.id ", |
||
493 | (microgrid_id,)) |
||
494 | row_meter = cursor_system.fetchone() |
||
495 | if row_meter is not None: |
||
496 | meter_list.append({"id": row_meter[0], |
||
497 | "name": row_meter[1] + '.Sell', |
||
498 | "energy_category_id": row_meter[2]}) |
||
499 | |||
500 | ################################################################################################################ |
||
501 | # Step 8: query associated heatpumps |
||
502 | ################################################################################################################ |
||
503 | cursor_system.execute(" SELECT p.id, mh.name, p.units, p.object_type " |
||
504 | " FROM tbl_microgrids_heatpumps mh, tbl_points p " |
||
505 | " WHERE mh.microgrid_id = %s AND mh.power_point_id = p.id ", |
||
506 | (microgrid_id,)) |
||
507 | row_point = cursor_system.fetchone() |
||
508 | if row_point is not None: |
||
509 | point_list.append({"id": row_point[0], |
||
510 | "name": row_point[1]+'.P', |
||
511 | "units": row_point[2], |
||
512 | "object_type": row_point[3]}) |
||
513 | |||
514 | cursor_system.execute(" SELECT m.id, mh.name, m.energy_category_id " |
||
515 | " FROM tbl_microgrids_heatpumps mh, tbl_meters m " |
||
516 | " WHERE mh.microgrid_id = %s AND mh.electricity_meter_id = m.id ", |
||
517 | (microgrid_id,)) |
||
518 | row_meter = cursor_system.fetchone() |
||
519 | if row_meter is not None: |
||
520 | meter_list.append({"id": row_meter[0], |
||
521 | "name": row_meter[1] + '.Electricity', |
||
522 | "energy_category_id": row_meter[2]}) |
||
523 | |||
524 | cursor_system.execute(" SELECT m.id, mh.name, m.energy_category_id " |
||
525 | " FROM tbl_microgrids_heatpumps mh, tbl_meters m " |
||
526 | " WHERE mh.microgrid_id = %s AND mh.heat_meter_id = m.id ", |
||
527 | (microgrid_id,)) |
||
528 | row_meter = cursor_system.fetchone() |
||
529 | if row_meter is not None: |
||
530 | meter_list.append({"id": row_meter[0], |
||
531 | "name": row_meter[1] + '.Heat', |
||
532 | "energy_category_id": row_meter[2]}) |
||
533 | |||
534 | cursor_system.execute(" SELECT m.id, mh.name, m.energy_category_id " |
||
535 | " FROM tbl_microgrids_heatpumps mh, tbl_meters m " |
||
536 | " WHERE mh.microgrid_id = %s AND mh.cooling_meter_id = m.id ", |
||
537 | (microgrid_id,)) |
||
538 | row_meter = cursor_system.fetchone() |
||
539 | if row_meter is not None: |
||
540 | meter_list.append({"id": row_meter[0], |
||
541 | "name": row_meter[1] + '.Cooling', |
||
542 | "energy_category_id": row_meter[2]}) |
||
543 | |||
544 | ################################################################################################################ |
||
545 | # Step 9: query associated loads |
||
546 | ################################################################################################################ |
||
547 | cursor_system.execute(" SELECT p.id, ml.name, p.units, p.object_type " |
||
548 | " FROM tbl_microgrids_loads ml, tbl_points p " |
||
549 | " WHERE ml.microgrid_id = %s AND ml.power_point_id = p.id ", |
||
550 | (microgrid_id,)) |
||
551 | row_point = cursor_system.fetchone() |
||
552 | if row_point is not None: |
||
553 | point_list.append({"id": row_point[0], |
||
554 | "name": row_point[1]+'.P', |
||
555 | "units": row_point[2], |
||
556 | "object_type": row_point[3]}) |
||
557 | |||
558 | cursor_system.execute(" SELECT m.id, ml.name, m.energy_category_id " |
||
559 | " FROM tbl_microgrids_loads ml, tbl_meters m " |
||
560 | " WHERE ml.microgrid_id = %s AND ml.meter_id = m.id ", |
||
561 | (microgrid_id,)) |
||
562 | row_meter = cursor_system.fetchone() |
||
563 | if row_meter is not None: |
||
564 | meter_list.append({"id": row_meter[0], |
||
565 | "name": row_meter[1], |
||
566 | "energy_category_id": row_meter[2]}) |
||
567 | ################################################################################################################ |
||
568 | # Step 10: query associated photovoltaics |
||
569 | ################################################################################################################ |
||
570 | cursor_system.execute(" SELECT p.id, mp.name, p.units, p.object_type " |
||
571 | " FROM tbl_microgrids_photovoltaics mp, tbl_points p " |
||
572 | " WHERE mp.id = %s AND mp.power_point_id = p.id ", |
||
573 | (microgrid_id,)) |
||
574 | row_point = cursor_system.fetchone() |
||
575 | if row_point is not None: |
||
576 | point_list.append({"id": row_point[0], |
||
577 | "name": row_point[1]+'.P', |
||
578 | "units": row_point[2], |
||
579 | "object_type": row_point[3]}) |
||
580 | |||
581 | cursor_system.execute(" SELECT m.id, mp.name, m.energy_category_id " |
||
582 | " FROM tbl_microgrids_photovoltaics mp, tbl_meters m " |
||
583 | " WHERE mp.id = %s AND mp.meter_id = m.id ", |
||
584 | (microgrid_id,)) |
||
585 | row_meter = cursor_system.fetchone() |
||
586 | if row_meter is not None: |
||
587 | meter_list.append({"id": row_meter[0], |
||
588 | "name": row_meter[1], |
||
589 | "energy_category_id": row_meter[2]}) |
||
590 | |||
591 | ################################################################################################################ |
||
592 | # Step 11: query associated schedules |
||
593 | ################################################################################################################ |
||
594 | schedule_list = list() |
||
595 | schedule_series_data = list() |
||
596 | cursor_system.execute(" SELECT start_time_of_day, end_time_of_day, peak_type, power " |
||
597 | " FROM tbl_microgrids_schedules " |
||
598 | " WHERE microgrid_id = %s " |
||
599 | " ORDER BY start_time_of_day ", |
||
600 | (microgrid_id,)) |
||
601 | rows_schedules = cursor_system.fetchall() |
||
602 | View Code Duplication | if rows_schedules is None or len(rows_schedules) == 0: |
|
0 ignored issues
–
show
|
|||
603 | pass |
||
604 | else: |
||
605 | for row_schedule in rows_schedules: |
||
606 | start_time = row_schedule[0] |
||
607 | end_time = row_schedule[1] |
||
608 | current_time = start_time |
||
609 | if row_schedule[2] == 'toppeak': |
||
610 | peak_type = 'Top-Peak' |
||
611 | elif row_schedule[2] == 'onpeak': |
||
612 | peak_type = 'On-Peak' |
||
613 | elif row_schedule[2] == 'midpeak': |
||
614 | peak_type = 'Mid-Peak' |
||
615 | elif row_schedule[2] == 'offpeak': |
||
616 | peak_type = 'Off-Peak' |
||
617 | elif row_schedule[2] == 'deep': |
||
618 | peak_type = 'Deep-Valley' |
||
619 | else: |
||
620 | peak_type = 'Unknown' |
||
621 | |||
622 | while current_time < end_time: |
||
623 | schedule_series_data.append(row_schedule[3]) |
||
624 | current_time = current_time + timedelta(minutes=30) |
||
625 | |||
626 | schedule_list.append({"start_time_of_day": '0' + str(start_time) if len(str(start_time)) == 7 |
||
627 | else str(start_time), |
||
628 | "end_time_of_day": '0' + str(end_time) if len(str(end_time)) == 7 |
||
629 | else str(end_time), |
||
630 | "peak_type": peak_type, |
||
631 | "power": row_schedule[3]}) |
||
632 | print('schedule_list:' + str(schedule_list)) |
||
633 | ################################################################################################################ |
||
634 | # Step 12: query associated sensors |
||
635 | ################################################################################################################ |
||
636 | cursor_system.execute(" SELECT p.id, p.name, p.units, p.object_type " |
||
637 | " FROM tbl_microgrids_sensors ms, tbl_sensors_points sp, tbl_points p " |
||
638 | " WHERE ms.microgrid_id = %s " |
||
639 | " AND ms.sensor_id = sp.sensor_id " |
||
640 | " AND sp.point_id = p.id ", |
||
641 | (microgrid_id,)) |
||
642 | rows_points = cursor_system.fetchall() |
||
643 | if rows_points is not None and len(rows_points) > 0: |
||
644 | for row_point in rows_points: |
||
645 | point_list.append({"id": row_point[0], |
||
646 | "name": row_point[1], |
||
647 | "units": row_point[2], |
||
648 | "object_type": row_point[3]}) |
||
649 | ################################################################################################################ |
||
650 | # Step 13: query associated meters data |
||
651 | ################################################################################################################ |
||
652 | timezone_offset = int(config.utc_offset[1:3]) * 60 + int(config.utc_offset[4:6]) |
||
653 | if config.utc_offset[0] == '-': |
||
654 | timezone_offset = -timezone_offset |
||
655 | |||
656 | cnx_energy = mysql.connector.connect(**config.myems_energy_db) |
||
657 | cursor_energy = cnx_energy.cursor() |
||
658 | |||
659 | meter_report_list = list() |
||
660 | |||
661 | for meter in meter_list: |
||
662 | cursor_energy.execute(" SELECT start_datetime_utc, actual_value " |
||
663 | " FROM tbl_meter_hourly " |
||
664 | " WHERE meter_id = %s " |
||
665 | " AND start_datetime_utc >= %s " |
||
666 | " AND start_datetime_utc < %s " |
||
667 | " ORDER BY start_datetime_utc ", |
||
668 | (meter['id'], |
||
669 | reporting_start_datetime_utc, |
||
670 | reporting_end_datetime_utc)) |
||
671 | rows_meter_hourly = cursor_energy.fetchall() |
||
672 | if rows_meter_hourly is not None and len(rows_meter_hourly) > 0: |
||
673 | meter_report = dict() |
||
674 | meter_report['timestamps'] = list() |
||
675 | meter_report['values'] = list() |
||
676 | meter_report['subtotal'] = Decimal(0.0) |
||
677 | |||
678 | for row_meter_hourly in rows_meter_hourly: |
||
679 | current_datetime_local = row_meter_hourly[0].replace(tzinfo=timezone.utc) + \ |
||
680 | timedelta(minutes=timezone_offset) |
||
681 | current_datetime = current_datetime_local.isoformat()[0:19] |
||
682 | |||
683 | actual_value = Decimal(0.0) if row_meter_hourly[1] is None else row_meter_hourly[1] |
||
684 | |||
685 | meter_report['timestamps'].append(current_datetime) |
||
686 | meter_report['values'].append(actual_value) |
||
687 | meter_report['subtotal'] += actual_value |
||
688 | meter_report['name'] = meter['name'] |
||
689 | meter_report['unit_of_measure'] = \ |
||
690 | energy_category_dict[meter['energy_category_id']]['unit_of_measure'] |
||
691 | |||
692 | meter_report_list.append(meter_report) |
||
693 | |||
694 | ################################################################################################################ |
||
695 | # Step 14: query associated points data |
||
696 | ################################################################################################################ |
||
697 | |||
698 | parameters_data = dict() |
||
699 | parameters_data['names'] = list() |
||
700 | parameters_data['timestamps'] = list() |
||
701 | parameters_data['values'] = list() |
||
702 | for point in point_list: |
||
703 | point_values = [] |
||
704 | point_timestamps = [] |
||
705 | if point['object_type'] == 'ENERGY_VALUE': |
||
706 | query = (" SELECT utc_date_time, actual_value " |
||
707 | " FROM tbl_energy_value " |
||
708 | " WHERE point_id = %s " |
||
709 | " AND utc_date_time BETWEEN %s AND %s " |
||
710 | " ORDER BY utc_date_time ") |
||
711 | cursor_historical.execute(query, (point['id'], |
||
712 | reporting_start_datetime_utc, |
||
713 | reporting_end_datetime_utc)) |
||
714 | rows = cursor_historical.fetchall() |
||
715 | |||
716 | if rows is not None and len(rows) > 0: |
||
717 | reporting_start_datetime_local = reporting_start_datetime_utc.replace(tzinfo=timezone.utc) + \ |
||
718 | timedelta(minutes=timezone_offset) |
||
719 | current_datetime_local = reporting_start_datetime_local |
||
720 | |||
721 | while current_datetime_local < rows[0][0].replace(tzinfo=timezone.utc) + \ |
||
722 | timedelta(minutes=timezone_offset): |
||
723 | point_timestamps.append(current_datetime_local.isoformat()[5:16]) |
||
724 | point_values.append(rows[0][1]) |
||
725 | current_datetime_local += timedelta(minutes=1) |
||
726 | |||
727 | for index in range(len(rows) - 1): |
||
728 | while current_datetime_local < rows[index + 1][0].replace(tzinfo=timezone.utc) + \ |
||
729 | timedelta(minutes=timezone_offset): |
||
730 | point_timestamps.append(current_datetime_local.isoformat()[5:16]) |
||
731 | point_values.append(rows[index][1]) |
||
732 | current_datetime_local += timedelta(minutes=1) |
||
733 | elif point['object_type'] == 'ANALOG_VALUE': |
||
734 | query = (" SELECT utc_date_time, actual_value " |
||
735 | " FROM tbl_analog_value " |
||
736 | " WHERE point_id = %s " |
||
737 | " AND utc_date_time BETWEEN %s AND %s " |
||
738 | " ORDER BY utc_date_time ") |
||
739 | cursor_historical.execute(query, (point['id'], |
||
740 | reporting_start_datetime_utc, |
||
741 | reporting_end_datetime_utc)) |
||
742 | rows = cursor_historical.fetchall() |
||
743 | |||
744 | if rows is not None and len(rows) > 0: |
||
745 | reporting_start_datetime_local = reporting_start_datetime_utc.replace(tzinfo=timezone.utc) + \ |
||
746 | timedelta(minutes=timezone_offset) |
||
747 | current_datetime_local = reporting_start_datetime_local |
||
748 | |||
749 | while current_datetime_local < rows[0][0].replace(tzinfo=timezone.utc) + \ |
||
750 | timedelta(minutes=timezone_offset): |
||
751 | point_timestamps.append(current_datetime_local.isoformat()[5:16]) |
||
752 | point_values.append(rows[0][1]) |
||
753 | current_datetime_local += timedelta(minutes=1) |
||
754 | |||
755 | for index in range(len(rows) - 1): |
||
756 | while current_datetime_local < rows[index + 1][0].replace(tzinfo=timezone.utc) + \ |
||
757 | timedelta(minutes=timezone_offset): |
||
758 | point_timestamps.append(current_datetime_local.isoformat()[5:16]) |
||
759 | point_values.append(rows[index][1]) |
||
760 | current_datetime_local += timedelta(minutes=1) |
||
761 | elif point['object_type'] == 'DIGITAL_VALUE': |
||
762 | query = (" SELECT utc_date_time, actual_value " |
||
763 | " FROM tbl_digital_value " |
||
764 | " WHERE point_id = %s " |
||
765 | " AND utc_date_time BETWEEN %s AND %s " |
||
766 | " ORDER BY utc_date_time ") |
||
767 | cursor_historical.execute(query, (point['id'], |
||
768 | reporting_start_datetime_utc, |
||
769 | reporting_end_datetime_utc)) |
||
770 | rows = cursor_historical.fetchall() |
||
771 | |||
772 | if rows is not None and len(rows) > 0: |
||
773 | reporting_start_datetime_local = reporting_start_datetime_utc.replace(tzinfo=timezone.utc) + \ |
||
774 | timedelta(minutes=timezone_offset) |
||
775 | current_datetime_local = reporting_start_datetime_local |
||
776 | |||
777 | while current_datetime_local < rows[0][0].replace(tzinfo=timezone.utc) + \ |
||
778 | timedelta(minutes=timezone_offset): |
||
779 | point_timestamps.append(current_datetime_local.isoformat()[5:16]) |
||
780 | point_values.append(rows[0][1]) |
||
781 | current_datetime_local += timedelta(minutes=1) |
||
782 | |||
783 | for index in range(len(rows) - 1): |
||
784 | while current_datetime_local < rows[index + 1][0].replace(tzinfo=timezone.utc) + \ |
||
785 | timedelta(minutes=timezone_offset): |
||
786 | point_timestamps.append(current_datetime_local.isoformat()[5:16]) |
||
787 | point_values.append(rows[index][1]) |
||
788 | current_datetime_local += timedelta(minutes=1) |
||
789 | |||
790 | parameters_data['names'].append(point['name'] + ' (' + point['units'] + ')') |
||
791 | parameters_data['timestamps'].append(point_timestamps) |
||
792 | parameters_data['values'].append(point_values) |
||
793 | |||
794 | if cursor_system: |
||
795 | cursor_system.close() |
||
796 | if cnx_system: |
||
797 | cnx_system.close() |
||
798 | |||
799 | if cursor_historical: |
||
800 | cursor_historical.close() |
||
801 | if cnx_historical: |
||
802 | cnx_historical.close() |
||
803 | ################################################################################################################ |
||
804 | # Step 15: construct the report |
||
805 | ################################################################################################################ |
||
806 | result = dict() |
||
807 | result['microgrid'] = meta_result |
||
808 | |||
809 | result['reporting_period'] = dict() |
||
810 | result['reporting_period']['names'] = list() |
||
811 | result['reporting_period']['units'] = list() |
||
812 | result['reporting_period']['subtotals'] = list() |
||
813 | result['reporting_period']['increment_rates'] = list() |
||
814 | result['reporting_period']['timestamps'] = list() |
||
815 | result['reporting_period']['values'] = list() |
||
816 | |||
817 | if meter_report_list is not None and len(meter_report_list) > 0: |
||
818 | for meter_report in meter_report_list: |
||
819 | result['reporting_period']['names'].append(meter_report['name']) |
||
820 | result['reporting_period']['units'].append(meter_report['unit_of_measure']) |
||
821 | result['reporting_period']['timestamps'].append(meter_report['timestamps']) |
||
822 | result['reporting_period']['values'].append(meter_report['values']) |
||
823 | result['reporting_period']['subtotals'].append(meter_report['subtotal']) |
||
824 | |||
825 | result['schedule'] = dict() |
||
826 | result['schedule']['series_data'] = schedule_series_data |
||
827 | result['schedule']['schedule_list'] = schedule_list |
||
828 | |||
829 | result['energy_indicators'] = dict() |
||
830 | result['energy_indicators']['today_charge_energy_value'] = today_charge_energy_value |
||
831 | result['energy_indicators']['today_discharge_energy_value'] = today_discharge_energy_value |
||
832 | result['energy_indicators']['total_charge_energy_value'] = total_charge_energy_value |
||
833 | result['energy_indicators']['total_discharge_energy_value'] = total_discharge_energy_value |
||
834 | |||
835 | result['revenue_indicators'] = dict() |
||
836 | result['revenue_indicators']['today_charge_revenue_value'] = today_charge_revenue_value |
||
837 | result['revenue_indicators']['today_discharge_revenue_value'] = today_discharge_revenue_value |
||
838 | result['revenue_indicators']['total_charge_revenue_value'] = total_charge_revenue_value |
||
839 | result['revenue_indicators']['total_discharge_revenue_value'] = total_discharge_revenue_value |
||
840 | |||
841 | result['carbon_indicators'] = dict() |
||
842 | result['carbon_indicators']['today_charge_carbon_value'] = today_charge_carbon_value |
||
843 | result['carbon_indicators']['today_discharge_carbon_value'] = today_discharge_carbon_value |
||
844 | result['carbon_indicators']['total_charge_carbon_value'] = total_charge_carbon_value |
||
845 | result['carbon_indicators']['total_discharge_carbon_value'] = total_discharge_carbon_value |
||
846 | |||
847 | result['parameters'] = { |
||
848 | "names": parameters_data['names'], |
||
849 | "timestamps": parameters_data['timestamps'], |
||
850 | "values": parameters_data['values'] |
||
851 | } |
||
852 | |||
853 | resp.text = json.dumps(result) |
||
854 | |||
855 |