@@ 108-622 (lines=515) @@ | ||
105 | # NOTE: returns None or the error string because that the logger object cannot be passed in as parameter |
|
106 | ######################################################################################################################## |
|
107 | ||
108 | def worker(combined_equipment): |
|
109 | #################################################################################################################### |
|
110 | # Step 1: get all input meters associated with the combined equipment |
|
111 | #################################################################################################################### |
|
112 | print("Step 1: get all input meters associated with the combined equipment " + str(combined_equipment['name'])) |
|
113 | ||
114 | meter_list = list() |
|
115 | cnx_system_db = None |
|
116 | cursor_system_db = None |
|
117 | try: |
|
118 | cnx_system_db = mysql.connector.connect(**config.myems_system_db) |
|
119 | cursor_system_db = cnx_system_db.cursor() |
|
120 | except Exception as e: |
|
121 | error_string = "Error in step 1.1 of combined_equipment_energy_input_item.worker " + str(e) |
|
122 | if cursor_system_db: |
|
123 | cursor_system_db.close() |
|
124 | if cnx_system_db: |
|
125 | cnx_system_db.close() |
|
126 | print(error_string) |
|
127 | return error_string |
|
128 | ||
129 | try: |
|
130 | cursor_system_db.execute(" SELECT m.id, m.name, m.energy_item_id " |
|
131 | " FROM tbl_meters m, tbl_combined_equipments_meters em " |
|
132 | " WHERE m.id = em.meter_id " |
|
133 | " AND m.is_counted = true " |
|
134 | " AND m.energy_item_id is NOT NULL " |
|
135 | " AND em.is_output = false " |
|
136 | " AND em.combined_equipment_id = %s ", |
|
137 | (combined_equipment['id'],)) |
|
138 | rows_meters = cursor_system_db.fetchall() |
|
139 | ||
140 | if rows_meters is not None and len(rows_meters) > 0: |
|
141 | for row in rows_meters: |
|
142 | meter_list.append({"id": row[0], |
|
143 | "name": row[1], |
|
144 | "energy_item_id": row[2]}) |
|
145 | ||
146 | except Exception as e: |
|
147 | error_string = "Error in step 1.2 of combined_equipment_energy_input_item.worker " + str(e) |
|
148 | if cursor_system_db: |
|
149 | cursor_system_db.close() |
|
150 | if cnx_system_db: |
|
151 | cnx_system_db.close() |
|
152 | print(error_string) |
|
153 | return error_string |
|
154 | ||
155 | #################################################################################################################### |
|
156 | # Step 2: get all input virtual meters associated with the combined equipment |
|
157 | #################################################################################################################### |
|
158 | print("Step 2: get all input virtual meters associated with the combined equipment") |
|
159 | virtual_meter_list = list() |
|
160 | ||
161 | try: |
|
162 | cursor_system_db.execute(" SELECT m.id, m.name, m.energy_item_id " |
|
163 | " FROM tbl_virtual_meters m, tbl_combined_equipments_virtual_meters em " |
|
164 | " WHERE m.id = em.virtual_meter_id " |
|
165 | " AND m.energy_item_id is NOT NULL " |
|
166 | " AND m.is_counted = true " |
|
167 | " AND em.is_output = false " |
|
168 | " AND em.combined_equipment_id = %s ", |
|
169 | (combined_equipment['id'],)) |
|
170 | rows_virtual_meters = cursor_system_db.fetchall() |
|
171 | ||
172 | if rows_virtual_meters is not None and len(rows_virtual_meters) > 0: |
|
173 | for row in rows_virtual_meters: |
|
174 | virtual_meter_list.append({"id": row[0], |
|
175 | "name": row[1], |
|
176 | "energy_item_id": row[2]}) |
|
177 | ||
178 | except Exception as e: |
|
179 | error_string = "Error in step 2.1 of combined_equipment_energy_input_item.worker " + str(e) |
|
180 | if cursor_system_db: |
|
181 | cursor_system_db.close() |
|
182 | if cnx_system_db: |
|
183 | cnx_system_db.close() |
|
184 | print(error_string) |
|
185 | return error_string |
|
186 | ||
187 | #################################################################################################################### |
|
188 | # Step 3: get all input offline meters associated with the combined equipment |
|
189 | #################################################################################################################### |
|
190 | print("Step 3: get all input offline meters associated with the combined equipment") |
|
191 | ||
192 | offline_meter_list = list() |
|
193 | ||
194 | try: |
|
195 | cursor_system_db.execute(" SELECT m.id, m.name, m.energy_item_id " |
|
196 | " FROM tbl_offline_meters m, tbl_combined_equipments_offline_meters em " |
|
197 | " WHERE m.id = em.offline_meter_id " |
|
198 | " AND m.energy_item_id is NOT NULL " |
|
199 | " AND m.is_counted = true " |
|
200 | " AND em.is_output = false " |
|
201 | " AND em.combined_equipment_id = %s ", |
|
202 | (combined_equipment['id'],)) |
|
203 | rows_offline_meters = cursor_system_db.fetchall() |
|
204 | ||
205 | if rows_offline_meters is not None and len(rows_offline_meters) > 0: |
|
206 | for row in rows_offline_meters: |
|
207 | offline_meter_list.append({"id": row[0], |
|
208 | "name": row[1], |
|
209 | "energy_item_id": row[2]}) |
|
210 | ||
211 | except Exception as e: |
|
212 | error_string = "Error in step 3.1 of combined_equipment_energy_input_item.worker " + str(e) |
|
213 | print(error_string) |
|
214 | return error_string |
|
215 | finally: |
|
216 | if cursor_system_db: |
|
217 | cursor_system_db.close() |
|
218 | if cnx_system_db: |
|
219 | cnx_system_db.close() |
|
220 | ||
221 | #################################################################################################################### |
|
222 | # Step 4: get all equipments associated with the combined equipment |
|
223 | #################################################################################################################### |
|
224 | print("Step 4: get all equipments associated with the combined equipment") |
|
225 | ||
226 | equipment_list = list() |
|
227 | ||
228 | try: |
|
229 | cursor_system_db.execute(" SELECT e.id, e.name " |
|
230 | " FROM tbl_equipments e, tbl_combined_equipments_equipments ce " |
|
231 | " WHERE e.id = ce.equipment_id " |
|
232 | " AND e.is_input_counted = true " |
|
233 | " AND ce.combined_equipment_id = %s ", |
|
234 | (combined_equipment['id'],)) |
|
235 | rows_equipments = cursor_system_db.fetchall() |
|
236 | ||
237 | if rows_equipments is not None and len(rows_equipments) > 0: |
|
238 | for row in rows_equipments: |
|
239 | equipment_list.append({"id": row[0], |
|
240 | "name": row[1]}) |
|
241 | ||
242 | except Exception as e: |
|
243 | error_string = "Error in step 4 of combined_equipment_energy_input_item.worker " + str(e) |
|
244 | print(error_string) |
|
245 | return error_string |
|
246 | finally: |
|
247 | if cursor_system_db: |
|
248 | cursor_system_db.close() |
|
249 | if cnx_system_db: |
|
250 | cnx_system_db.close() |
|
251 | ||
252 | #################################################################################################################### |
|
253 | # stop to the next combined equipment if this combined equipment is empty |
|
254 | #################################################################################################################### |
|
255 | if (meter_list is None or len(meter_list) == 0) and \ |
|
256 | (virtual_meter_list is None or len(virtual_meter_list) == 0) and \ |
|
257 | (offline_meter_list is None or len(offline_meter_list) == 0) and \ |
|
258 | (equipment_list is None or len(equipment_list) == 0): |
|
259 | print("This is an empty combined equipment ") |
|
260 | return None |
|
261 | ||
262 | #################################################################################################################### |
|
263 | # Step 5: determine start datetime and end datetime to aggregate |
|
264 | #################################################################################################################### |
|
265 | print("Step 5: determine start datetime and end datetime to aggregate") |
|
266 | cnx_energy_db = None |
|
267 | cursor_energy_db = None |
|
268 | try: |
|
269 | cnx_energy_db = mysql.connector.connect(**config.myems_energy_db) |
|
270 | cursor_energy_db = cnx_energy_db.cursor() |
|
271 | except Exception as e: |
|
272 | error_string = "Error in step 5.1 of combined_equipment_energy_input_item.worker " + str(e) |
|
273 | if cursor_energy_db: |
|
274 | cursor_energy_db.close() |
|
275 | if cnx_energy_db: |
|
276 | cnx_energy_db.close() |
|
277 | print(error_string) |
|
278 | return error_string |
|
279 | ||
280 | try: |
|
281 | query = (" SELECT MAX(start_datetime_utc) " |
|
282 | " FROM tbl_combined_equipment_input_item_hourly " |
|
283 | " WHERE combined_equipment_id = %s ") |
|
284 | cursor_energy_db.execute(query, (combined_equipment['id'],)) |
|
285 | row_datetime = cursor_energy_db.fetchone() |
|
286 | start_datetime_utc = datetime.strptime(config.start_datetime_utc, '%Y-%m-%d %H:%M:%S') |
|
287 | start_datetime_utc = start_datetime_utc.replace(minute=0, second=0, microsecond=0, tzinfo=None) |
|
288 | ||
289 | if row_datetime is not None and len(row_datetime) > 0 and isinstance(row_datetime[0], datetime): |
|
290 | # replace second and microsecond with 0 |
|
291 | # note: do not replace minute in case of calculating in half hourly |
|
292 | start_datetime_utc = row_datetime[0].replace(second=0, microsecond=0, tzinfo=None) |
|
293 | # start from the next time slot |
|
294 | start_datetime_utc += timedelta(minutes=config.minutes_to_count) |
|
295 | ||
296 | end_datetime_utc = datetime.utcnow().replace(second=0, microsecond=0, tzinfo=None) |
|
297 | ||
298 | print("start_datetime_utc: " + start_datetime_utc.isoformat()[0:19] |
|
299 | + "end_datetime_utc: " + end_datetime_utc.isoformat()[0:19]) |
|
300 | ||
301 | except Exception as e: |
|
302 | error_string = "Error in step 5.2 of combined_equipment_energy_input_item.worker " + str(e) |
|
303 | if cursor_energy_db: |
|
304 | cursor_energy_db.close() |
|
305 | if cnx_energy_db: |
|
306 | cnx_energy_db.close() |
|
307 | print(error_string) |
|
308 | return error_string |
|
309 | ||
310 | #################################################################################################################### |
|
311 | # Step 6: for each meter in list, get energy input data from energy database |
|
312 | #################################################################################################################### |
|
313 | energy_meter_hourly = dict() |
|
314 | try: |
|
315 | if meter_list is not None and len(meter_list) > 0: |
|
316 | for meter in meter_list: |
|
317 | meter_id = str(meter['id']) |
|
318 | ||
319 | query = (" SELECT start_datetime_utc, actual_value " |
|
320 | " FROM tbl_meter_hourly " |
|
321 | " WHERE meter_id = %s " |
|
322 | " AND start_datetime_utc >= %s " |
|
323 | " AND start_datetime_utc < %s " |
|
324 | " ORDER BY start_datetime_utc ") |
|
325 | cursor_energy_db.execute(query, (meter_id, start_datetime_utc, end_datetime_utc,)) |
|
326 | rows_energy_values = cursor_energy_db.fetchall() |
|
327 | if rows_energy_values is None or len(rows_energy_values) == 0: |
|
328 | energy_meter_hourly[meter_id] = None |
|
329 | else: |
|
330 | energy_meter_hourly[meter_id] = dict() |
|
331 | for row_energy_value in rows_energy_values: |
|
332 | energy_meter_hourly[meter_id][row_energy_value[0]] = row_energy_value[1] |
|
333 | except Exception as e: |
|
334 | error_string = "Error in step 6.1 of combined_equipment_energy_input_item.worker " + str(e) |
|
335 | if cursor_energy_db: |
|
336 | cursor_energy_db.close() |
|
337 | if cnx_energy_db: |
|
338 | cnx_energy_db.close() |
|
339 | print(error_string) |
|
340 | return error_string |
|
341 | ||
342 | #################################################################################################################### |
|
343 | # Step 7: for each virtual meter in list, get energy input data from energy database |
|
344 | #################################################################################################################### |
|
345 | energy_virtual_meter_hourly = dict() |
|
346 | if virtual_meter_list is not None and len(virtual_meter_list) > 0: |
|
347 | try: |
|
348 | for virtual_meter in virtual_meter_list: |
|
349 | virtual_meter_id = str(virtual_meter['id']) |
|
350 | ||
351 | query = (" SELECT start_datetime_utc, actual_value " |
|
352 | " FROM tbl_virtual_meter_hourly " |
|
353 | " WHERE virtual_meter_id = %s " |
|
354 | " AND start_datetime_utc >= %s " |
|
355 | " AND start_datetime_utc < %s " |
|
356 | " ORDER BY start_datetime_utc ") |
|
357 | cursor_energy_db.execute(query, (virtual_meter_id, start_datetime_utc, end_datetime_utc,)) |
|
358 | rows_energy_values = cursor_energy_db.fetchall() |
|
359 | if rows_energy_values is None or len(rows_energy_values) == 0: |
|
360 | energy_virtual_meter_hourly[virtual_meter_id] = None |
|
361 | else: |
|
362 | energy_virtual_meter_hourly[virtual_meter_id] = dict() |
|
363 | for row_energy_value in rows_energy_values: |
|
364 | energy_virtual_meter_hourly[virtual_meter_id][row_energy_value[0]] = row_energy_value[1] |
|
365 | except Exception as e: |
|
366 | error_string = "Error in step 7.1 of combined_equipment_energy_input_item.worker " + str(e) |
|
367 | if cursor_energy_db: |
|
368 | cursor_energy_db.close() |
|
369 | if cnx_energy_db: |
|
370 | cnx_energy_db.close() |
|
371 | print(error_string) |
|
372 | return error_string |
|
373 | ||
374 | #################################################################################################################### |
|
375 | # Step 8: for each offline meter in list, get energy input data from energy database |
|
376 | #################################################################################################################### |
|
377 | energy_offline_meter_hourly = dict() |
|
378 | if offline_meter_list is not None and len(offline_meter_list) > 0: |
|
379 | try: |
|
380 | for offline_meter in offline_meter_list: |
|
381 | offline_meter_id = str(offline_meter['id']) |
|
382 | ||
383 | query = (" SELECT start_datetime_utc, actual_value " |
|
384 | " FROM tbl_offline_meter_hourly " |
|
385 | " WHERE offline_meter_id = %s " |
|
386 | " AND start_datetime_utc >= %s " |
|
387 | " AND start_datetime_utc < %s " |
|
388 | " ORDER BY start_datetime_utc ") |
|
389 | cursor_energy_db.execute(query, (offline_meter_id, start_datetime_utc, end_datetime_utc,)) |
|
390 | rows_energy_values = cursor_energy_db.fetchall() |
|
391 | if rows_energy_values is None or len(rows_energy_values) == 0: |
|
392 | energy_offline_meter_hourly[offline_meter_id] = None |
|
393 | else: |
|
394 | energy_offline_meter_hourly[offline_meter_id] = dict() |
|
395 | for row_energy_value in rows_energy_values: |
|
396 | energy_offline_meter_hourly[offline_meter_id][row_energy_value[0]] = row_energy_value[1] |
|
397 | ||
398 | except Exception as e: |
|
399 | error_string = "Error in step 8.1 of combined_equipment_energy_input_item.worker " + str(e) |
|
400 | if cursor_energy_db: |
|
401 | cursor_energy_db.close() |
|
402 | if cnx_energy_db: |
|
403 | cnx_energy_db.close() |
|
404 | print(error_string) |
|
405 | return error_string |
|
406 | ||
407 | #################################################################################################################### |
|
408 | # Step 9: for each equipment in list, get energy input data from energy database |
|
409 | #################################################################################################################### |
|
410 | energy_equipment_hourly = dict() |
|
411 | if equipment_list is not None and len(equipment_list) > 0: |
|
412 | try: |
|
413 | for equipment in equipment_list: |
|
414 | equipment_id = str(equipment['id']) |
|
415 | query = (" SELECT start_datetime_utc, energy_category_id, actual_value " |
|
416 | " FROM tbl_equipment_input_item_hourly " |
|
417 | " WHERE equipment_id = %s " |
|
418 | " AND start_datetime_utc >= %s " |
|
419 | " AND start_datetime_utc < %s " |
|
420 | " ORDER BY start_datetime_utc ") |
|
421 | cursor_energy_db.execute(query, (equipment_id, start_datetime_utc, end_datetime_utc,)) |
|
422 | rows_energy_values = cursor_energy_db.fetchall() |
|
423 | if rows_energy_values is None or len(rows_energy_values) == 0: |
|
424 | energy_equipment_hourly[equipment_id] = None |
|
425 | else: |
|
426 | energy_equipment_hourly[equipment_id] = dict() |
|
427 | for row_value in rows_energy_values: |
|
428 | current_datetime_utc = row_value[0] |
|
429 | if current_datetime_utc not in energy_equipment_hourly[equipment_id]: |
|
430 | energy_equipment_hourly[equipment_id][current_datetime_utc] = dict() |
|
431 | energy_category_id = row_value[1] |
|
432 | actual_value = row_value[2] |
|
433 | energy_equipment_hourly[equipment_id][current_datetime_utc][energy_category_id] = \ |
|
434 | actual_value |
|
435 | except Exception as e: |
|
436 | error_string = "Error in step 9 of combined_equipment_energy_input_item.worker " + str(e) |
|
437 | if cursor_energy_db: |
|
438 | cursor_energy_db.close() |
|
439 | if cnx_energy_db: |
|
440 | cnx_energy_db.close() |
|
441 | print(error_string) |
|
442 | return error_string |
|
443 | ||
444 | #################################################################################################################### |
|
445 | # Step 10: determine common time slot to aggregate |
|
446 | #################################################################################################################### |
|
447 | ||
448 | common_start_datetime_utc = start_datetime_utc |
|
449 | common_end_datetime_utc = end_datetime_utc |
|
450 | ||
451 | print("Getting common time slot of energy values for all meters") |
|
452 | if energy_meter_hourly is not None and len(energy_meter_hourly) > 0: |
|
453 | for meter_id, energy_hourly in energy_meter_hourly.items(): |
|
454 | if energy_hourly is None or len(energy_hourly) == 0: |
|
455 | common_start_datetime_utc = None |
|
456 | common_end_datetime_utc = None |
|
457 | break |
|
458 | else: |
|
459 | if common_start_datetime_utc < min(energy_hourly.keys()): |
|
460 | common_start_datetime_utc = min(energy_hourly.keys()) |
|
461 | if common_end_datetime_utc > max(energy_hourly.keys()): |
|
462 | common_end_datetime_utc = max(energy_hourly.keys()) |
|
463 | ||
464 | print("Getting common time slot of energy values for all virtual meters") |
|
465 | if common_start_datetime_utc is not None and common_start_datetime_utc is not None: |
|
466 | if energy_virtual_meter_hourly is not None and len(energy_virtual_meter_hourly) > 0: |
|
467 | for meter_id, energy_hourly in energy_virtual_meter_hourly.items(): |
|
468 | if energy_hourly is None or len(energy_hourly) == 0: |
|
469 | common_start_datetime_utc = None |
|
470 | common_end_datetime_utc = None |
|
471 | break |
|
472 | else: |
|
473 | if common_start_datetime_utc < min(energy_hourly.keys()): |
|
474 | common_start_datetime_utc = min(energy_hourly.keys()) |
|
475 | if common_end_datetime_utc > max(energy_hourly.keys()): |
|
476 | common_end_datetime_utc = max(energy_hourly.keys()) |
|
477 | ||
478 | print("Getting common time slot of energy values for all offline meters") |
|
479 | if common_start_datetime_utc is not None and common_start_datetime_utc is not None: |
|
480 | if energy_offline_meter_hourly is not None and len(energy_offline_meter_hourly) > 0: |
|
481 | for meter_id, energy_hourly in energy_offline_meter_hourly.items(): |
|
482 | if energy_hourly is None or len(energy_hourly) == 0: |
|
483 | common_start_datetime_utc = None |
|
484 | common_end_datetime_utc = None |
|
485 | break |
|
486 | else: |
|
487 | if common_start_datetime_utc < min(energy_hourly.keys()): |
|
488 | common_start_datetime_utc = min(energy_hourly.keys()) |
|
489 | if common_end_datetime_utc > max(energy_hourly.keys()): |
|
490 | common_end_datetime_utc = max(energy_hourly.keys()) |
|
491 | ||
492 | print("Getting common time slot of energy values for all equipments") |
|
493 | if common_start_datetime_utc is not None and common_start_datetime_utc is not None: |
|
494 | if energy_equipment_hourly is not None and len(energy_equipment_hourly) > 0: |
|
495 | for equipment_id, energy_hourly in energy_equipment_hourly.items(): |
|
496 | if energy_hourly is None or len(energy_hourly) == 0: |
|
497 | common_start_datetime_utc = None |
|
498 | common_end_datetime_utc = None |
|
499 | break |
|
500 | else: |
|
501 | if common_start_datetime_utc < min(energy_hourly.keys()): |
|
502 | common_start_datetime_utc = min(energy_hourly.keys()) |
|
503 | if common_end_datetime_utc > max(energy_hourly.keys()): |
|
504 | common_end_datetime_utc = max(energy_hourly.keys()) |
|
505 | ||
506 | if (energy_meter_hourly is None or len(energy_meter_hourly) == 0) and \ |
|
507 | (energy_virtual_meter_hourly is None or len(energy_virtual_meter_hourly) == 0) and \ |
|
508 | (energy_offline_meter_hourly is None or len(energy_offline_meter_hourly) == 0) and \ |
|
509 | (energy_equipment_hourly is None or len(energy_equipment_hourly) == 0): |
|
510 | # There isn't any energy data |
|
511 | print("There isn't any energy data") |
|
512 | # continue the for combined equipment loop to the next combined equipment |
|
513 | print("continue the for combined equipment loop to the next combined equipment") |
|
514 | if cursor_energy_db: |
|
515 | cursor_energy_db.close() |
|
516 | if cnx_energy_db: |
|
517 | cnx_energy_db.close() |
|
518 | return None |
|
519 | ||
520 | print("common_start_datetime_utc: " + str(common_start_datetime_utc)) |
|
521 | print("common_end_datetime_utc: " + str(common_end_datetime_utc)) |
|
522 | ||
523 | #################################################################################################################### |
|
524 | # Step 11: aggregate energy data in the common time slot by energy items and hourly |
|
525 | #################################################################################################################### |
|
526 | ||
527 | print("Step 11: aggregate energy data in the common time slot by energy items and hourly") |
|
528 | aggregated_values = list() |
|
529 | try: |
|
530 | current_datetime_utc = common_start_datetime_utc |
|
531 | while common_start_datetime_utc is not None \ |
|
532 | and common_end_datetime_utc is not None \ |
|
533 | and current_datetime_utc <= common_end_datetime_utc: |
|
534 | aggregated_value = dict() |
|
535 | aggregated_value['start_datetime_utc'] = current_datetime_utc |
|
536 | aggregated_value['meta_data'] = dict() |
|
537 | ||
538 | if meter_list is not None and len(meter_list) > 0: |
|
539 | for meter in meter_list: |
|
540 | meter_id = str(meter['id']) |
|
541 | energy_item_id = meter['energy_item_id'] |
|
542 | actual_value = energy_meter_hourly[meter_id].get(current_datetime_utc, Decimal(0.0)) |
|
543 | aggregated_value['meta_data'][energy_item_id] = \ |
|
544 | aggregated_value['meta_data'].get(energy_item_id, Decimal(0.0)) + actual_value |
|
545 | ||
546 | if virtual_meter_list is not None and len(virtual_meter_list) > 0: |
|
547 | for virtual_meter in virtual_meter_list: |
|
548 | virtual_meter_id = str(virtual_meter['id']) |
|
549 | energy_item_id = virtual_meter['energy_item_id'] |
|
550 | actual_value = energy_virtual_meter_hourly[virtual_meter_id].get(current_datetime_utc, Decimal(0.0)) |
|
551 | aggregated_value['meta_data'][energy_item_id] = \ |
|
552 | aggregated_value['meta_data'].get(energy_item_id, Decimal(0.0)) + actual_value |
|
553 | ||
554 | if offline_meter_list is not None and len(offline_meter_list) > 0: |
|
555 | for offline_meter in offline_meter_list: |
|
556 | offline_meter_id = str(offline_meter['id']) |
|
557 | energy_item_id = offline_meter['energy_item_id'] |
|
558 | actual_value = energy_offline_meter_hourly[offline_meter_id].get(current_datetime_utc, Decimal(0.0)) |
|
559 | aggregated_value['meta_data'][energy_item_id] = \ |
|
560 | aggregated_value['meta_data'].get(energy_item_id, Decimal(0.0)) + actual_value |
|
561 | ||
562 | if equipment_list is not None and len(equipment_list) > 0: |
|
563 | for equipment in equipment_list: |
|
564 | equipment_id = str(equipment['id']) |
|
565 | meta_data_dict = energy_equipment_hourly[equipment_id].get(current_datetime_utc, None) |
|
566 | if meta_data_dict is not None and len(meta_data_dict) > 0: |
|
567 | for energy_category_id, actual_value in meta_data_dict.items(): |
|
568 | aggregated_value['meta_data'][energy_category_id] = \ |
|
569 | aggregated_value['meta_data'].get(energy_category_id, Decimal(0.0)) + actual_value |
|
570 | ||
571 | aggregated_values.append(aggregated_value) |
|
572 | ||
573 | current_datetime_utc += timedelta(minutes=config.minutes_to_count) |
|
574 | ||
575 | except Exception as e: |
|
576 | error_string = "Error in step 11 of combined_equipment_energy_input_item.worker " + str(e) |
|
577 | if cursor_energy_db: |
|
578 | cursor_energy_db.close() |
|
579 | if cnx_energy_db: |
|
580 | cnx_energy_db.close() |
|
581 | print(error_string) |
|
582 | return error_string |
|
583 | ||
584 | #################################################################################################################### |
|
585 | # Step 12: save energy data to energy database |
|
586 | #################################################################################################################### |
|
587 | print("Step 12: save energy data to energy database") |
|
588 | ||
589 | if len(aggregated_values) > 0: |
|
590 | try: |
|
591 | add_values = (" INSERT INTO tbl_combined_equipment_input_item_hourly " |
|
592 | " (combined_equipment_id, " |
|
593 | " energy_item_id, " |
|
594 | " start_datetime_utc, " |
|
595 | " actual_value) " |
|
596 | " VALUES ") |
|
597 | ||
598 | for aggregated_value in aggregated_values: |
|
599 | for energy_item_id, actual_value in aggregated_value['meta_data'].items(): |
|
600 | add_values += " (" + str(combined_equipment['id']) + "," |
|
601 | add_values += " " + str(energy_item_id) + "," |
|
602 | add_values += "'" + aggregated_value['start_datetime_utc'].isoformat()[0:19] + "'," |
|
603 | add_values += str(actual_value) + "), " |
|
604 | print("add_values:" + add_values) |
|
605 | # trim ", " at the end of string and then execute |
|
606 | cursor_energy_db.execute(add_values[:-2]) |
|
607 | cnx_energy_db.commit() |
|
608 | ||
609 | except Exception as e: |
|
610 | error_string = "Error in step 12.1 of combined_equipment_energy_input_item.worker " + str(e) |
|
611 | print(error_string) |
|
612 | return error_string |
|
613 | finally: |
|
614 | if cursor_energy_db: |
|
615 | cursor_energy_db.close() |
|
616 | if cnx_energy_db: |
|
617 | cnx_energy_db.close() |
|
618 | else: |
|
619 | if cursor_energy_db: |
|
620 | cursor_energy_db.close() |
|
621 | if cnx_energy_db: |
|
622 | cnx_energy_db.close() |
|
623 |
@@ 108-619 (lines=512) @@ | ||
105 | # NOTE: returns None or the error string because that the logger object cannot be passed in as parameter |
|
106 | ######################################################################################################################## |
|
107 | ||
108 | def worker(combined_equipment): |
|
109 | #################################################################################################################### |
|
110 | # Step 1: get all output meters associated with the combined equipment |
|
111 | #################################################################################################################### |
|
112 | print("Step 1: get all output meters associated with the combined equipment " + str(combined_equipment['name'])) |
|
113 | ||
114 | meter_list = list() |
|
115 | cnx_system_db = None |
|
116 | cursor_system_db = None |
|
117 | try: |
|
118 | cnx_system_db = mysql.connector.connect(**config.myems_system_db) |
|
119 | cursor_system_db = cnx_system_db.cursor() |
|
120 | except Exception as e: |
|
121 | error_string = "Error in step 1.1 of combined_equipment_energy_output_category.worker " + str(e) |
|
122 | if cursor_system_db: |
|
123 | cursor_system_db.close() |
|
124 | if cnx_system_db: |
|
125 | cnx_system_db.close() |
|
126 | print(error_string) |
|
127 | return error_string |
|
128 | ||
129 | try: |
|
130 | cursor_system_db.execute(" SELECT m.id, m.name, m.energy_category_id " |
|
131 | " FROM tbl_meters m, tbl_combined_equipments_meters em " |
|
132 | " WHERE m.id = em.meter_id " |
|
133 | " AND m.is_counted = true " |
|
134 | " AND em.is_output = true " |
|
135 | " AND em.combined_equipment_id = %s ", |
|
136 | (combined_equipment['id'],)) |
|
137 | rows_meters = cursor_system_db.fetchall() |
|
138 | ||
139 | if rows_meters is not None and len(rows_meters) > 0: |
|
140 | for row in rows_meters: |
|
141 | meter_list.append({"id": row[0], |
|
142 | "name": row[1], |
|
143 | "energy_category_id": row[2]}) |
|
144 | ||
145 | except Exception as e: |
|
146 | error_string = "Error in step 1.2 of combined_equipment_energy_output_category.worker " + str(e) |
|
147 | if cursor_system_db: |
|
148 | cursor_system_db.close() |
|
149 | if cnx_system_db: |
|
150 | cnx_system_db.close() |
|
151 | print(error_string) |
|
152 | return error_string |
|
153 | ||
154 | #################################################################################################################### |
|
155 | # Step 2: get all output virtual meters associated with the combined equipment |
|
156 | #################################################################################################################### |
|
157 | print("Step 2: get all output virtual meters associated with the combined equipment") |
|
158 | virtual_meter_list = list() |
|
159 | ||
160 | try: |
|
161 | cursor_system_db.execute(" SELECT m.id, m.name, m.energy_category_id " |
|
162 | " FROM tbl_virtual_meters m, tbl_combined_equipments_virtual_meters em " |
|
163 | " WHERE m.id = em.virtual_meter_id " |
|
164 | " AND m.is_counted = true " |
|
165 | " AND em.is_output = true " |
|
166 | " AND em.combined_equipment_id = %s ", |
|
167 | (combined_equipment['id'],)) |
|
168 | rows_virtual_meters = cursor_system_db.fetchall() |
|
169 | ||
170 | if rows_virtual_meters is not None and len(rows_virtual_meters) > 0: |
|
171 | for row in rows_virtual_meters: |
|
172 | virtual_meter_list.append({"id": row[0], |
|
173 | "name": row[1], |
|
174 | "energy_category_id": row[2]}) |
|
175 | ||
176 | except Exception as e: |
|
177 | error_string = "Error in step 2.1 of combined_equipment_energy_output_category.worker " + str(e) |
|
178 | if cursor_system_db: |
|
179 | cursor_system_db.close() |
|
180 | if cnx_system_db: |
|
181 | cnx_system_db.close() |
|
182 | print(error_string) |
|
183 | return error_string |
|
184 | ||
185 | #################################################################################################################### |
|
186 | # Step 3: get all output offline meters associated with the combined equipment |
|
187 | #################################################################################################################### |
|
188 | print("Step 3: get all output offline meters associated with the combined equipment") |
|
189 | ||
190 | offline_meter_list = list() |
|
191 | ||
192 | try: |
|
193 | cursor_system_db.execute(" SELECT m.id, m.name, m.energy_category_id " |
|
194 | " FROM tbl_offline_meters m, tbl_combined_equipments_offline_meters em " |
|
195 | " WHERE m.id = em.offline_meter_id " |
|
196 | " AND m.is_counted = true " |
|
197 | " AND em.is_output = true " |
|
198 | " AND em.combined_equipment_id = %s ", |
|
199 | (combined_equipment['id'],)) |
|
200 | rows_offline_meters = cursor_system_db.fetchall() |
|
201 | ||
202 | if rows_offline_meters is not None and len(rows_offline_meters) > 0: |
|
203 | for row in rows_offline_meters: |
|
204 | offline_meter_list.append({"id": row[0], |
|
205 | "name": row[1], |
|
206 | "energy_category_id": row[2]}) |
|
207 | ||
208 | except Exception as e: |
|
209 | error_string = "Error in step 3.1 of combined_equipment_energy_output_category.worker " + str(e) |
|
210 | print(error_string) |
|
211 | return error_string |
|
212 | finally: |
|
213 | if cursor_system_db: |
|
214 | cursor_system_db.close() |
|
215 | if cnx_system_db: |
|
216 | cnx_system_db.close() |
|
217 | ||
218 | #################################################################################################################### |
|
219 | # Step 4: get all equipments associated with the combined equipment |
|
220 | #################################################################################################################### |
|
221 | print("Step 4: get all equipments associated with the combined equipment") |
|
222 | ||
223 | equipment_list = list() |
|
224 | ||
225 | try: |
|
226 | cursor_system_db.execute(" SELECT e.id, e.name " |
|
227 | " FROM tbl_equipments e, tbl_combined_equipments_equipments ce " |
|
228 | " WHERE e.id = ce.equipment_id " |
|
229 | " AND e.is_output_counted = true " |
|
230 | " AND ce.combined_equipment_id = %s ", |
|
231 | (combined_equipment['id'],)) |
|
232 | rows_equipments = cursor_system_db.fetchall() |
|
233 | ||
234 | if rows_equipments is not None and len(rows_equipments) > 0: |
|
235 | for row in rows_equipments: |
|
236 | equipment_list.append({"id": row[0], |
|
237 | "name": row[1]}) |
|
238 | ||
239 | except Exception as e: |
|
240 | error_string = "Error in step 4 of combined_equipment_energy_output_category.worker " + str(e) |
|
241 | print(error_string) |
|
242 | return error_string |
|
243 | finally: |
|
244 | if cursor_system_db: |
|
245 | cursor_system_db.close() |
|
246 | if cnx_system_db: |
|
247 | cnx_system_db.close() |
|
248 | ||
249 | #################################################################################################################### |
|
250 | # stop to the next combined equipment if this combined 3equipment is empty |
|
251 | #################################################################################################################### |
|
252 | if (meter_list is None or len(meter_list) == 0) and \ |
|
253 | (virtual_meter_list is None or len(virtual_meter_list) == 0) and \ |
|
254 | (offline_meter_list is None or len(offline_meter_list) == 0) and \ |
|
255 | (equipment_list is None or len(equipment_list) == 0): |
|
256 | print("This is an empty combined equipment ") |
|
257 | return None |
|
258 | ||
259 | #################################################################################################################### |
|
260 | # Step 5: determine start datetime and end datetime to aggregate |
|
261 | #################################################################################################################### |
|
262 | print("Step 5: determine start datetime and end datetime to aggregate") |
|
263 | cnx_energy_db = None |
|
264 | cursor_energy_db = None |
|
265 | try: |
|
266 | cnx_energy_db = mysql.connector.connect(**config.myems_energy_db) |
|
267 | cursor_energy_db = cnx_energy_db.cursor() |
|
268 | except Exception as e: |
|
269 | error_string = "Error in step 5.1 of combined_equipment_energy_output_category.worker " + str(e) |
|
270 | if cursor_energy_db: |
|
271 | cursor_energy_db.close() |
|
272 | if cnx_energy_db: |
|
273 | cnx_energy_db.close() |
|
274 | print(error_string) |
|
275 | return error_string |
|
276 | ||
277 | try: |
|
278 | query = (" SELECT MAX(start_datetime_utc) " |
|
279 | " FROM tbl_combined_equipment_output_category_hourly " |
|
280 | " WHERE combined_equipment_id = %s ") |
|
281 | cursor_energy_db.execute(query, (combined_equipment['id'],)) |
|
282 | row_datetime = cursor_energy_db.fetchone() |
|
283 | start_datetime_utc = datetime.strptime(config.start_datetime_utc, '%Y-%m-%d %H:%M:%S') |
|
284 | start_datetime_utc = start_datetime_utc.replace(minute=0, second=0, microsecond=0, tzinfo=None) |
|
285 | ||
286 | if row_datetime is not None and len(row_datetime) > 0 and isinstance(row_datetime[0], datetime): |
|
287 | # replace second and microsecond with 0 |
|
288 | # note: do not replace minute in case of calculating in half hourly |
|
289 | start_datetime_utc = row_datetime[0].replace(second=0, microsecond=0, tzinfo=None) |
|
290 | # start from the next time slot |
|
291 | start_datetime_utc += timedelta(minutes=config.minutes_to_count) |
|
292 | ||
293 | end_datetime_utc = datetime.utcnow().replace(second=0, microsecond=0, tzinfo=None) |
|
294 | ||
295 | print("start_datetime_utc: " + start_datetime_utc.isoformat()[0:19] |
|
296 | + "end_datetime_utc: " + end_datetime_utc.isoformat()[0:19]) |
|
297 | ||
298 | except Exception as e: |
|
299 | error_string = "Error in step 5.2 of combined_equipment_energy_output_category.worker " + str(e) |
|
300 | if cursor_energy_db: |
|
301 | cursor_energy_db.close() |
|
302 | if cnx_energy_db: |
|
303 | cnx_energy_db.close() |
|
304 | print(error_string) |
|
305 | return error_string |
|
306 | ||
307 | #################################################################################################################### |
|
308 | # Step 6: for each meter in list, get energy output data from energy database |
|
309 | #################################################################################################################### |
|
310 | energy_meter_hourly = dict() |
|
311 | try: |
|
312 | if meter_list is not None and len(meter_list) > 0: |
|
313 | for meter in meter_list: |
|
314 | meter_id = str(meter['id']) |
|
315 | ||
316 | query = (" SELECT start_datetime_utc, actual_value " |
|
317 | " FROM tbl_meter_hourly " |
|
318 | " WHERE meter_id = %s " |
|
319 | " AND start_datetime_utc >= %s " |
|
320 | " AND start_datetime_utc < %s " |
|
321 | " ORDER BY start_datetime_utc ") |
|
322 | cursor_energy_db.execute(query, (meter_id, start_datetime_utc, end_datetime_utc,)) |
|
323 | rows_energy_values = cursor_energy_db.fetchall() |
|
324 | if rows_energy_values is None or len(rows_energy_values) == 0: |
|
325 | energy_meter_hourly[meter_id] = None |
|
326 | else: |
|
327 | energy_meter_hourly[meter_id] = dict() |
|
328 | for row_energy_value in rows_energy_values: |
|
329 | energy_meter_hourly[meter_id][row_energy_value[0]] = row_energy_value[1] |
|
330 | except Exception as e: |
|
331 | error_string = "Error in step 6.1 of combined_equipment_energy_output_category.worker " + str(e) |
|
332 | if cursor_energy_db: |
|
333 | cursor_energy_db.close() |
|
334 | if cnx_energy_db: |
|
335 | cnx_energy_db.close() |
|
336 | print(error_string) |
|
337 | return error_string |
|
338 | ||
339 | #################################################################################################################### |
|
340 | # Step 7: for each virtual meter in list, get energy output data from energy database |
|
341 | #################################################################################################################### |
|
342 | energy_virtual_meter_hourly = dict() |
|
343 | if virtual_meter_list is not None and len(virtual_meter_list) > 0: |
|
344 | try: |
|
345 | for virtual_meter in virtual_meter_list: |
|
346 | virtual_meter_id = str(virtual_meter['id']) |
|
347 | ||
348 | query = (" SELECT start_datetime_utc, actual_value " |
|
349 | " FROM tbl_virtual_meter_hourly " |
|
350 | " WHERE virtual_meter_id = %s " |
|
351 | " AND start_datetime_utc >= %s " |
|
352 | " AND start_datetime_utc < %s " |
|
353 | " ORDER BY start_datetime_utc ") |
|
354 | cursor_energy_db.execute(query, (virtual_meter_id, start_datetime_utc, end_datetime_utc,)) |
|
355 | rows_energy_values = cursor_energy_db.fetchall() |
|
356 | if rows_energy_values is None or len(rows_energy_values) == 0: |
|
357 | energy_virtual_meter_hourly[virtual_meter_id] = None |
|
358 | else: |
|
359 | energy_virtual_meter_hourly[virtual_meter_id] = dict() |
|
360 | for row_energy_value in rows_energy_values: |
|
361 | energy_virtual_meter_hourly[virtual_meter_id][row_energy_value[0]] = row_energy_value[1] |
|
362 | except Exception as e: |
|
363 | error_string = "Error in step 7.1 of combined_equipment_energy_output_category.worker " + str(e) |
|
364 | if cursor_energy_db: |
|
365 | cursor_energy_db.close() |
|
366 | if cnx_energy_db: |
|
367 | cnx_energy_db.close() |
|
368 | print(error_string) |
|
369 | return error_string |
|
370 | ||
371 | #################################################################################################################### |
|
372 | # Step 8: for each offline meter in list, get energy output data from energy database |
|
373 | #################################################################################################################### |
|
374 | energy_offline_meter_hourly = dict() |
|
375 | if offline_meter_list is not None and len(offline_meter_list) > 0: |
|
376 | try: |
|
377 | for offline_meter in offline_meter_list: |
|
378 | offline_meter_id = str(offline_meter['id']) |
|
379 | ||
380 | query = (" SELECT start_datetime_utc, actual_value " |
|
381 | " FROM tbl_offline_meter_hourly " |
|
382 | " WHERE offline_meter_id = %s " |
|
383 | " AND start_datetime_utc >= %s " |
|
384 | " AND start_datetime_utc < %s " |
|
385 | " ORDER BY start_datetime_utc ") |
|
386 | cursor_energy_db.execute(query, (offline_meter_id, start_datetime_utc, end_datetime_utc,)) |
|
387 | rows_energy_values = cursor_energy_db.fetchall() |
|
388 | if rows_energy_values is None or len(rows_energy_values) == 0: |
|
389 | energy_offline_meter_hourly[offline_meter_id] = None |
|
390 | else: |
|
391 | energy_offline_meter_hourly[offline_meter_id] = dict() |
|
392 | for row_energy_value in rows_energy_values: |
|
393 | energy_offline_meter_hourly[offline_meter_id][row_energy_value[0]] = row_energy_value[1] |
|
394 | ||
395 | except Exception as e: |
|
396 | error_string = "Error in step 8.1 of combined_equipment_energy_output_category.worker " + str(e) |
|
397 | if cursor_energy_db: |
|
398 | cursor_energy_db.close() |
|
399 | if cnx_energy_db: |
|
400 | cnx_energy_db.close() |
|
401 | print(error_string) |
|
402 | return error_string |
|
403 | ||
404 | #################################################################################################################### |
|
405 | # Step 9: for each equipment in list, get energy output data from energy database |
|
406 | #################################################################################################################### |
|
407 | energy_equipment_hourly = dict() |
|
408 | if equipment_list is not None and len(equipment_list) > 0: |
|
409 | try: |
|
410 | for equipment in equipment_list: |
|
411 | equipment_id = str(equipment['id']) |
|
412 | query = (" SELECT start_datetime_utc, energy_category_id, actual_value " |
|
413 | " FROM tbl_equipment_output_category_hourly " |
|
414 | " WHERE equipment_id = %s " |
|
415 | " AND start_datetime_utc >= %s " |
|
416 | " AND start_datetime_utc < %s " |
|
417 | " ORDER BY start_datetime_utc ") |
|
418 | cursor_energy_db.execute(query, (equipment_id, start_datetime_utc, end_datetime_utc,)) |
|
419 | rows_energy_values = cursor_energy_db.fetchall() |
|
420 | if rows_energy_values is None or len(rows_energy_values) == 0: |
|
421 | energy_equipment_hourly[equipment_id] = None |
|
422 | else: |
|
423 | energy_equipment_hourly[equipment_id] = dict() |
|
424 | for row_value in rows_energy_values: |
|
425 | current_datetime_utc = row_value[0] |
|
426 | if current_datetime_utc not in energy_equipment_hourly[equipment_id]: |
|
427 | energy_equipment_hourly[equipment_id][current_datetime_utc] = dict() |
|
428 | energy_category_id = row_value[1] |
|
429 | actual_value = row_value[2] |
|
430 | energy_equipment_hourly[equipment_id][current_datetime_utc][energy_category_id] = \ |
|
431 | actual_value |
|
432 | except Exception as e: |
|
433 | error_string = "Error in step 9 of combined_equipment_energy_output_category.worker " + str(e) |
|
434 | if cursor_energy_db: |
|
435 | cursor_energy_db.close() |
|
436 | if cnx_energy_db: |
|
437 | cnx_energy_db.close() |
|
438 | print(error_string) |
|
439 | return error_string |
|
440 | ||
441 | #################################################################################################################### |
|
442 | # Step 10: determine common time slot to aggregate |
|
443 | #################################################################################################################### |
|
444 | ||
445 | common_start_datetime_utc = start_datetime_utc |
|
446 | common_end_datetime_utc = end_datetime_utc |
|
447 | ||
448 | print("Getting common time slot of energy values for all meters") |
|
449 | if energy_meter_hourly is not None and len(energy_meter_hourly) > 0: |
|
450 | for meter_id, energy_hourly in energy_meter_hourly.items(): |
|
451 | if energy_hourly is None or len(energy_hourly) == 0: |
|
452 | common_start_datetime_utc = None |
|
453 | common_end_datetime_utc = None |
|
454 | break |
|
455 | else: |
|
456 | if common_start_datetime_utc < min(energy_hourly.keys()): |
|
457 | common_start_datetime_utc = min(energy_hourly.keys()) |
|
458 | if common_end_datetime_utc > max(energy_hourly.keys()): |
|
459 | common_end_datetime_utc = max(energy_hourly.keys()) |
|
460 | ||
461 | print("Getting common time slot of energy values for all virtual meters") |
|
462 | if common_start_datetime_utc is not None and common_start_datetime_utc is not None: |
|
463 | if energy_virtual_meter_hourly is not None and len(energy_virtual_meter_hourly) > 0: |
|
464 | for meter_id, energy_hourly in energy_virtual_meter_hourly.items(): |
|
465 | if energy_hourly is None or len(energy_hourly) == 0: |
|
466 | common_start_datetime_utc = None |
|
467 | common_end_datetime_utc = None |
|
468 | break |
|
469 | else: |
|
470 | if common_start_datetime_utc < min(energy_hourly.keys()): |
|
471 | common_start_datetime_utc = min(energy_hourly.keys()) |
|
472 | if common_end_datetime_utc > max(energy_hourly.keys()): |
|
473 | common_end_datetime_utc = max(energy_hourly.keys()) |
|
474 | ||
475 | print("Getting common time slot of energy values for all offline meters") |
|
476 | if common_start_datetime_utc is not None and common_start_datetime_utc is not None: |
|
477 | if energy_offline_meter_hourly is not None and len(energy_offline_meter_hourly) > 0: |
|
478 | for meter_id, energy_hourly in energy_offline_meter_hourly.items(): |
|
479 | if energy_hourly is None or len(energy_hourly) == 0: |
|
480 | common_start_datetime_utc = None |
|
481 | common_end_datetime_utc = None |
|
482 | break |
|
483 | else: |
|
484 | if common_start_datetime_utc < min(energy_hourly.keys()): |
|
485 | common_start_datetime_utc = min(energy_hourly.keys()) |
|
486 | if common_end_datetime_utc > max(energy_hourly.keys()): |
|
487 | common_end_datetime_utc = max(energy_hourly.keys()) |
|
488 | ||
489 | print("Getting common time slot of energy values for all equipments...") |
|
490 | if common_start_datetime_utc is not None and common_start_datetime_utc is not None: |
|
491 | if energy_equipment_hourly is not None and len(energy_equipment_hourly) > 0: |
|
492 | for equipment_id, energy_hourly in energy_equipment_hourly.items(): |
|
493 | if energy_hourly is None or len(energy_hourly) == 0: |
|
494 | common_start_datetime_utc = None |
|
495 | common_end_datetime_utc = None |
|
496 | break |
|
497 | else: |
|
498 | if common_start_datetime_utc < min(energy_hourly.keys()): |
|
499 | common_start_datetime_utc = min(energy_hourly.keys()) |
|
500 | if common_end_datetime_utc > max(energy_hourly.keys()): |
|
501 | common_end_datetime_utc = max(energy_hourly.keys()) |
|
502 | ||
503 | if (energy_meter_hourly is None or len(energy_meter_hourly) == 0) and \ |
|
504 | (energy_virtual_meter_hourly is None or len(energy_virtual_meter_hourly) == 0) and \ |
|
505 | (energy_offline_meter_hourly is None or len(energy_offline_meter_hourly) == 0) and \ |
|
506 | (energy_equipment_hourly is None or len(energy_equipment_hourly) == 0): |
|
507 | # There isn't any energy data |
|
508 | print("There isn't any energy data") |
|
509 | # continue the for combined equipment loop to the next combined equipment |
|
510 | print("continue the for combined equipment loop to the next combined equipment") |
|
511 | if cursor_energy_db: |
|
512 | cursor_energy_db.close() |
|
513 | if cnx_energy_db: |
|
514 | cnx_energy_db.close() |
|
515 | return None |
|
516 | ||
517 | print("common_start_datetime_utc: " + str(common_start_datetime_utc)) |
|
518 | print("common_end_datetime_utc: " + str(common_end_datetime_utc)) |
|
519 | ||
520 | #################################################################################################################### |
|
521 | # Step 11: aggregate energy data in the common time slot by energy categories and hourly |
|
522 | #################################################################################################################### |
|
523 | ||
524 | print("Step 11: aggregate energy data in the common time slot by energy categories and hourly") |
|
525 | aggregated_values = list() |
|
526 | try: |
|
527 | current_datetime_utc = common_start_datetime_utc |
|
528 | while common_start_datetime_utc is not None \ |
|
529 | and common_end_datetime_utc is not None \ |
|
530 | and current_datetime_utc <= common_end_datetime_utc: |
|
531 | aggregated_value = dict() |
|
532 | aggregated_value['start_datetime_utc'] = current_datetime_utc |
|
533 | aggregated_value['meta_data'] = dict() |
|
534 | ||
535 | if meter_list is not None and len(meter_list) > 0: |
|
536 | for meter in meter_list: |
|
537 | meter_id = str(meter['id']) |
|
538 | energy_category_id = meter['energy_category_id'] |
|
539 | actual_value = energy_meter_hourly[meter_id].get(current_datetime_utc, Decimal(0.0)) |
|
540 | aggregated_value['meta_data'][energy_category_id] = \ |
|
541 | aggregated_value['meta_data'].get(energy_category_id, Decimal(0.0)) + actual_value |
|
542 | ||
543 | if virtual_meter_list is not None and len(virtual_meter_list) > 0: |
|
544 | for virtual_meter in virtual_meter_list: |
|
545 | virtual_meter_id = str(virtual_meter['id']) |
|
546 | energy_category_id = virtual_meter['energy_category_id'] |
|
547 | actual_value = energy_virtual_meter_hourly[virtual_meter_id].get(current_datetime_utc, Decimal(0.0)) |
|
548 | aggregated_value['meta_data'][energy_category_id] = \ |
|
549 | aggregated_value['meta_data'].get(energy_category_id, Decimal(0.0)) + actual_value |
|
550 | ||
551 | if offline_meter_list is not None and len(offline_meter_list) > 0: |
|
552 | for offline_meter in offline_meter_list: |
|
553 | offline_meter_id = str(offline_meter['id']) |
|
554 | energy_category_id = offline_meter['energy_category_id'] |
|
555 | actual_value = energy_offline_meter_hourly[offline_meter_id].get(current_datetime_utc, Decimal(0.0)) |
|
556 | aggregated_value['meta_data'][energy_category_id] = \ |
|
557 | aggregated_value['meta_data'].get(energy_category_id, Decimal(0.0)) + actual_value |
|
558 | ||
559 | if equipment_list is not None and len(equipment_list) > 0: |
|
560 | for equipment in equipment_list: |
|
561 | equipment_id = str(equipment['id']) |
|
562 | meta_data_dict = energy_equipment_hourly[equipment_id].get(current_datetime_utc, None) |
|
563 | if meta_data_dict is not None and len(meta_data_dict) > 0: |
|
564 | for energy_category_id, actual_value in meta_data_dict.items(): |
|
565 | aggregated_value['meta_data'][energy_category_id] = \ |
|
566 | aggregated_value['meta_data'].get(energy_category_id, Decimal(0.0)) + actual_value |
|
567 | ||
568 | aggregated_values.append(aggregated_value) |
|
569 | ||
570 | current_datetime_utc += timedelta(minutes=config.minutes_to_count) |
|
571 | ||
572 | except Exception as e: |
|
573 | error_string = "Error in step 11 of combined_equipment_energy_output_category.worker " + str(e) |
|
574 | if cursor_energy_db: |
|
575 | cursor_energy_db.close() |
|
576 | if cnx_energy_db: |
|
577 | cnx_energy_db.close() |
|
578 | print(error_string) |
|
579 | return error_string |
|
580 | ||
581 | #################################################################################################################### |
|
582 | # Step 12: save energy data to energy database |
|
583 | #################################################################################################################### |
|
584 | print("Step 12: save energy data to energy database") |
|
585 | ||
586 | if len(aggregated_values) > 0: |
|
587 | try: |
|
588 | add_values = (" INSERT INTO tbl_combined_equipment_output_category_hourly " |
|
589 | " (combined_equipment_id, " |
|
590 | " energy_category_id, " |
|
591 | " start_datetime_utc, " |
|
592 | " actual_value) " |
|
593 | " VALUES ") |
|
594 | ||
595 | for aggregated_value in aggregated_values: |
|
596 | for energy_category_id, actual_value in aggregated_value['meta_data'].items(): |
|
597 | add_values += " (" + str(combined_equipment['id']) + "," |
|
598 | add_values += " " + str(energy_category_id) + "," |
|
599 | add_values += "'" + aggregated_value['start_datetime_utc'].isoformat()[0:19] + "'," |
|
600 | add_values += str(actual_value) + "), " |
|
601 | print("add_values:" + add_values) |
|
602 | # trim ", " at the end of string and then execute |
|
603 | cursor_energy_db.execute(add_values[:-2]) |
|
604 | cnx_energy_db.commit() |
|
605 | ||
606 | except Exception as e: |
|
607 | error_string = "Error in step 12.1 of combined_equipment_energy_output_category.worker " + str(e) |
|
608 | print(error_string) |
|
609 | return error_string |
|
610 | finally: |
|
611 | if cursor_energy_db: |
|
612 | cursor_energy_db.close() |
|
613 | if cnx_energy_db: |
|
614 | cnx_energy_db.close() |
|
615 | else: |
|
616 | if cursor_energy_db: |
|
617 | cursor_energy_db.close() |
|
618 | if cnx_energy_db: |
|
619 | cnx_energy_db.close() |
|
620 |
@@ 108-619 (lines=512) @@ | ||
105 | # NOTE: returns None or the error string because that the logger object cannot be passed in as parameter |
|
106 | ######################################################################################################################## |
|
107 | ||
108 | def worker(combined_equipment): |
|
109 | #################################################################################################################### |
|
110 | # Step 1: get all input meters associated with the combined equipment |
|
111 | #################################################################################################################### |
|
112 | print("Step 1: get all input meters associated with the combined equipment " + str(combined_equipment['name'])) |
|
113 | ||
114 | meter_list = list() |
|
115 | cnx_system_db = None |
|
116 | cursor_system_db = None |
|
117 | try: |
|
118 | cnx_system_db = mysql.connector.connect(**config.myems_system_db) |
|
119 | cursor_system_db = cnx_system_db.cursor() |
|
120 | except Exception as e: |
|
121 | error_string = "Error in step 1.1 of combined_equipment_energy_input_category.worker " + str(e) |
|
122 | if cursor_system_db: |
|
123 | cursor_system_db.close() |
|
124 | if cnx_system_db: |
|
125 | cnx_system_db.close() |
|
126 | print(error_string) |
|
127 | return error_string |
|
128 | ||
129 | try: |
|
130 | cursor_system_db.execute(" SELECT m.id, m.name, m.energy_category_id " |
|
131 | " FROM tbl_meters m, tbl_combined_equipments_meters em " |
|
132 | " WHERE m.id = em.meter_id " |
|
133 | " AND m.is_counted = true " |
|
134 | " AND em.is_output = false " |
|
135 | " AND em.combined_equipment_id = %s ", |
|
136 | (combined_equipment['id'],)) |
|
137 | rows_meters = cursor_system_db.fetchall() |
|
138 | ||
139 | if rows_meters is not None and len(rows_meters) > 0: |
|
140 | for row in rows_meters: |
|
141 | meter_list.append({"id": row[0], |
|
142 | "name": row[1], |
|
143 | "energy_category_id": row[2]}) |
|
144 | ||
145 | except Exception as e: |
|
146 | error_string = "Error in step 1.2 of combined_equipment_energy_input_category.worker " + str(e) |
|
147 | if cursor_system_db: |
|
148 | cursor_system_db.close() |
|
149 | if cnx_system_db: |
|
150 | cnx_system_db.close() |
|
151 | print(error_string) |
|
152 | return error_string |
|
153 | ||
154 | #################################################################################################################### |
|
155 | # Step 2: get all input virtual meters associated with the combined equipment |
|
156 | #################################################################################################################### |
|
157 | print("Step 2: get all input virtual meters associated with the combined equipment") |
|
158 | virtual_meter_list = list() |
|
159 | ||
160 | try: |
|
161 | cursor_system_db.execute(" SELECT m.id, m.name, m.energy_category_id " |
|
162 | " FROM tbl_virtual_meters m, tbl_combined_equipments_virtual_meters em " |
|
163 | " WHERE m.id = em.virtual_meter_id " |
|
164 | " AND m.is_counted = true " |
|
165 | " AND em.is_output = false " |
|
166 | " AND em.combined_equipment_id = %s ", |
|
167 | (combined_equipment['id'],)) |
|
168 | rows_virtual_meters = cursor_system_db.fetchall() |
|
169 | ||
170 | if rows_virtual_meters is not None and len(rows_virtual_meters) > 0: |
|
171 | for row in rows_virtual_meters: |
|
172 | virtual_meter_list.append({"id": row[0], |
|
173 | "name": row[1], |
|
174 | "energy_category_id": row[2]}) |
|
175 | ||
176 | except Exception as e: |
|
177 | error_string = "Error in step 2.1 of combined_equipment_energy_input_category.worker " + str(e) |
|
178 | if cursor_system_db: |
|
179 | cursor_system_db.close() |
|
180 | if cnx_system_db: |
|
181 | cnx_system_db.close() |
|
182 | print(error_string) |
|
183 | return error_string |
|
184 | ||
185 | #################################################################################################################### |
|
186 | # Step 3: get all input offline meters associated with the combined equipment |
|
187 | #################################################################################################################### |
|
188 | print("Step 3: get all input offline meters associated with the combined equipment") |
|
189 | ||
190 | offline_meter_list = list() |
|
191 | ||
192 | try: |
|
193 | cursor_system_db.execute(" SELECT m.id, m.name, m.energy_category_id " |
|
194 | " FROM tbl_offline_meters m, tbl_combined_equipments_offline_meters em " |
|
195 | " WHERE m.id = em.offline_meter_id " |
|
196 | " AND m.is_counted = true " |
|
197 | " AND em.is_output = false " |
|
198 | " AND em.combined_equipment_id = %s ", |
|
199 | (combined_equipment['id'],)) |
|
200 | rows_offline_meters = cursor_system_db.fetchall() |
|
201 | ||
202 | if rows_offline_meters is not None and len(rows_offline_meters) > 0: |
|
203 | for row in rows_offline_meters: |
|
204 | offline_meter_list.append({"id": row[0], |
|
205 | "name": row[1], |
|
206 | "energy_category_id": row[2]}) |
|
207 | ||
208 | except Exception as e: |
|
209 | error_string = "Error in step 3.1 of combined_equipment_energy_input_category.worker " + str(e) |
|
210 | print(error_string) |
|
211 | return error_string |
|
212 | finally: |
|
213 | if cursor_system_db: |
|
214 | cursor_system_db.close() |
|
215 | if cnx_system_db: |
|
216 | cnx_system_db.close() |
|
217 | ||
218 | #################################################################################################################### |
|
219 | # Step 4: get all equipments associated with the combined equipment |
|
220 | #################################################################################################################### |
|
221 | print("Step 4: get all equipments associated with the combined equipment") |
|
222 | ||
223 | equipment_list = list() |
|
224 | ||
225 | try: |
|
226 | cursor_system_db.execute(" SELECT e.id, e.name " |
|
227 | " FROM tbl_equipments e, tbl_combined_equipments_equipments ce " |
|
228 | " WHERE e.id = ce.equipment_id " |
|
229 | " AND e.is_input_counted = true " |
|
230 | " AND ce.combined_equipment_id = %s ", |
|
231 | (combined_equipment['id'],)) |
|
232 | rows_equipments = cursor_system_db.fetchall() |
|
233 | ||
234 | if rows_equipments is not None and len(rows_equipments) > 0: |
|
235 | for row in rows_equipments: |
|
236 | equipment_list.append({"id": row[0], |
|
237 | "name": row[1]}) |
|
238 | ||
239 | except Exception as e: |
|
240 | error_string = "Error in step 4 of combined_equipment_energy_input_category.worker " + str(e) |
|
241 | print(error_string) |
|
242 | return error_string |
|
243 | finally: |
|
244 | if cursor_system_db: |
|
245 | cursor_system_db.close() |
|
246 | if cnx_system_db: |
|
247 | cnx_system_db.close() |
|
248 | ||
249 | #################################################################################################################### |
|
250 | # stop to the next combined equipment if this combined equipment is empty |
|
251 | #################################################################################################################### |
|
252 | if (meter_list is None or len(meter_list) == 0) and \ |
|
253 | (virtual_meter_list is None or len(virtual_meter_list) == 0) and \ |
|
254 | (offline_meter_list is None or len(offline_meter_list) == 0) and \ |
|
255 | (equipment_list is None or len(equipment_list) == 0): |
|
256 | print("This is an empty combined equipment ") |
|
257 | return None |
|
258 | ||
259 | #################################################################################################################### |
|
260 | # Step 5: determine start datetime and end datetime to aggregate |
|
261 | #################################################################################################################### |
|
262 | print("Step 5: determine start datetime and end datetime to aggregate") |
|
263 | cnx_energy_db = None |
|
264 | cursor_energy_db = None |
|
265 | try: |
|
266 | cnx_energy_db = mysql.connector.connect(**config.myems_energy_db) |
|
267 | cursor_energy_db = cnx_energy_db.cursor() |
|
268 | except Exception as e: |
|
269 | error_string = "Error in step 5.1 of combined_equipment_energy_input_category.worker " + str(e) |
|
270 | if cursor_energy_db: |
|
271 | cursor_energy_db.close() |
|
272 | if cnx_energy_db: |
|
273 | cnx_energy_db.close() |
|
274 | print(error_string) |
|
275 | return error_string |
|
276 | ||
277 | try: |
|
278 | query = (" SELECT MAX(start_datetime_utc) " |
|
279 | " FROM tbl_combined_equipment_input_category_hourly " |
|
280 | " WHERE combined_equipment_id = %s ") |
|
281 | cursor_energy_db.execute(query, (combined_equipment['id'],)) |
|
282 | row_datetime = cursor_energy_db.fetchone() |
|
283 | start_datetime_utc = datetime.strptime(config.start_datetime_utc, '%Y-%m-%d %H:%M:%S') |
|
284 | start_datetime_utc = start_datetime_utc.replace(minute=0, second=0, microsecond=0, tzinfo=None) |
|
285 | ||
286 | if row_datetime is not None and len(row_datetime) > 0 and isinstance(row_datetime[0], datetime): |
|
287 | # replace second and microsecond with 0 |
|
288 | # note: do not replace minute in case of calculating in half hourly |
|
289 | start_datetime_utc = row_datetime[0].replace(second=0, microsecond=0, tzinfo=None) |
|
290 | # start from the next time slot |
|
291 | start_datetime_utc += timedelta(minutes=config.minutes_to_count) |
|
292 | ||
293 | end_datetime_utc = datetime.utcnow().replace(second=0, microsecond=0, tzinfo=None) |
|
294 | ||
295 | print("start_datetime_utc: " + start_datetime_utc.isoformat()[0:19] |
|
296 | + "end_datetime_utc: " + end_datetime_utc.isoformat()[0:19]) |
|
297 | ||
298 | except Exception as e: |
|
299 | error_string = "Error in step 5.2 of combined_equipment_energy_input_category.worker " + str(e) |
|
300 | if cursor_energy_db: |
|
301 | cursor_energy_db.close() |
|
302 | if cnx_energy_db: |
|
303 | cnx_energy_db.close() |
|
304 | print(error_string) |
|
305 | return error_string |
|
306 | ||
307 | #################################################################################################################### |
|
308 | # Step 6: for each meter in list, get energy input data from energy database |
|
309 | #################################################################################################################### |
|
310 | energy_meter_hourly = dict() |
|
311 | try: |
|
312 | if meter_list is not None and len(meter_list) > 0: |
|
313 | for meter in meter_list: |
|
314 | meter_id = str(meter['id']) |
|
315 | ||
316 | query = (" SELECT start_datetime_utc, actual_value " |
|
317 | " FROM tbl_meter_hourly " |
|
318 | " WHERE meter_id = %s " |
|
319 | " AND start_datetime_utc >= %s " |
|
320 | " AND start_datetime_utc < %s " |
|
321 | " ORDER BY start_datetime_utc ") |
|
322 | cursor_energy_db.execute(query, (meter_id, start_datetime_utc, end_datetime_utc,)) |
|
323 | rows_energy_values = cursor_energy_db.fetchall() |
|
324 | if rows_energy_values is None or len(rows_energy_values) == 0: |
|
325 | energy_meter_hourly[meter_id] = None |
|
326 | else: |
|
327 | energy_meter_hourly[meter_id] = dict() |
|
328 | for row_energy_value in rows_energy_values: |
|
329 | energy_meter_hourly[meter_id][row_energy_value[0]] = row_energy_value[1] |
|
330 | except Exception as e: |
|
331 | error_string = "Error in step 6.1 of combined_equipment_energy_input_category.worker " + str(e) |
|
332 | if cursor_energy_db: |
|
333 | cursor_energy_db.close() |
|
334 | if cnx_energy_db: |
|
335 | cnx_energy_db.close() |
|
336 | print(error_string) |
|
337 | return error_string |
|
338 | ||
339 | #################################################################################################################### |
|
340 | # Step 7: for each virtual meter in list, get energy input data from energy database |
|
341 | #################################################################################################################### |
|
342 | energy_virtual_meter_hourly = dict() |
|
343 | if virtual_meter_list is not None and len(virtual_meter_list) > 0: |
|
344 | try: |
|
345 | for virtual_meter in virtual_meter_list: |
|
346 | virtual_meter_id = str(virtual_meter['id']) |
|
347 | ||
348 | query = (" SELECT start_datetime_utc, actual_value " |
|
349 | " FROM tbl_virtual_meter_hourly " |
|
350 | " WHERE virtual_meter_id = %s " |
|
351 | " AND start_datetime_utc >= %s " |
|
352 | " AND start_datetime_utc < %s " |
|
353 | " ORDER BY start_datetime_utc ") |
|
354 | cursor_energy_db.execute(query, (virtual_meter_id, start_datetime_utc, end_datetime_utc,)) |
|
355 | rows_energy_values = cursor_energy_db.fetchall() |
|
356 | if rows_energy_values is None or len(rows_energy_values) == 0: |
|
357 | energy_virtual_meter_hourly[virtual_meter_id] = None |
|
358 | else: |
|
359 | energy_virtual_meter_hourly[virtual_meter_id] = dict() |
|
360 | for row_energy_value in rows_energy_values: |
|
361 | energy_virtual_meter_hourly[virtual_meter_id][row_energy_value[0]] = row_energy_value[1] |
|
362 | except Exception as e: |
|
363 | error_string = "Error in step 7.1 of combined_equipment_energy_input_category.worker " + str(e) |
|
364 | if cursor_energy_db: |
|
365 | cursor_energy_db.close() |
|
366 | if cnx_energy_db: |
|
367 | cnx_energy_db.close() |
|
368 | print(error_string) |
|
369 | return error_string |
|
370 | ||
371 | #################################################################################################################### |
|
372 | # Step 8: for each offline meter in list, get energy input data from energy database |
|
373 | #################################################################################################################### |
|
374 | energy_offline_meter_hourly = dict() |
|
375 | if offline_meter_list is not None and len(offline_meter_list) > 0: |
|
376 | try: |
|
377 | for offline_meter in offline_meter_list: |
|
378 | offline_meter_id = str(offline_meter['id']) |
|
379 | ||
380 | query = (" SELECT start_datetime_utc, actual_value " |
|
381 | " FROM tbl_offline_meter_hourly " |
|
382 | " WHERE offline_meter_id = %s " |
|
383 | " AND start_datetime_utc >= %s " |
|
384 | " AND start_datetime_utc < %s " |
|
385 | " ORDER BY start_datetime_utc ") |
|
386 | cursor_energy_db.execute(query, (offline_meter_id, start_datetime_utc, end_datetime_utc,)) |
|
387 | rows_energy_values = cursor_energy_db.fetchall() |
|
388 | if rows_energy_values is None or len(rows_energy_values) == 0: |
|
389 | energy_offline_meter_hourly[offline_meter_id] = None |
|
390 | else: |
|
391 | energy_offline_meter_hourly[offline_meter_id] = dict() |
|
392 | for row_energy_value in rows_energy_values: |
|
393 | energy_offline_meter_hourly[offline_meter_id][row_energy_value[0]] = row_energy_value[1] |
|
394 | ||
395 | except Exception as e: |
|
396 | error_string = "Error in step 8.1 of combined_equipment_energy_input_category.worker " + str(e) |
|
397 | if cursor_energy_db: |
|
398 | cursor_energy_db.close() |
|
399 | if cnx_energy_db: |
|
400 | cnx_energy_db.close() |
|
401 | print(error_string) |
|
402 | return error_string |
|
403 | ||
404 | #################################################################################################################### |
|
405 | # Step 9: for each equipment in list, get energy input data from energy database |
|
406 | #################################################################################################################### |
|
407 | energy_equipment_hourly = dict() |
|
408 | if equipment_list is not None and len(equipment_list) > 0: |
|
409 | try: |
|
410 | for equipment in equipment_list: |
|
411 | equipment_id = str(equipment['id']) |
|
412 | query = (" SELECT start_datetime_utc, energy_category_id, actual_value " |
|
413 | " FROM tbl_equipment_input_category_hourly " |
|
414 | " WHERE equipment_id = %s " |
|
415 | " AND start_datetime_utc >= %s " |
|
416 | " AND start_datetime_utc < %s " |
|
417 | " ORDER BY start_datetime_utc ") |
|
418 | cursor_energy_db.execute(query, (equipment_id, start_datetime_utc, end_datetime_utc,)) |
|
419 | rows_energy_values = cursor_energy_db.fetchall() |
|
420 | if rows_energy_values is None or len(rows_energy_values) == 0: |
|
421 | energy_equipment_hourly[equipment_id] = None |
|
422 | else: |
|
423 | energy_equipment_hourly[equipment_id] = dict() |
|
424 | for row_value in rows_energy_values: |
|
425 | current_datetime_utc = row_value[0] |
|
426 | if current_datetime_utc not in energy_equipment_hourly[equipment_id]: |
|
427 | energy_equipment_hourly[equipment_id][current_datetime_utc] = dict() |
|
428 | energy_category_id = row_value[1] |
|
429 | actual_value = row_value[2] |
|
430 | energy_equipment_hourly[equipment_id][current_datetime_utc][energy_category_id] = \ |
|
431 | actual_value |
|
432 | except Exception as e: |
|
433 | error_string = "Error in step 9 of combined_equipment_energy_input_category.worker " + str(e) |
|
434 | if cursor_energy_db: |
|
435 | cursor_energy_db.close() |
|
436 | if cnx_energy_db: |
|
437 | cnx_energy_db.close() |
|
438 | print(error_string) |
|
439 | return error_string |
|
440 | ||
441 | #################################################################################################################### |
|
442 | # Step 10: determine common time slot to aggregate |
|
443 | #################################################################################################################### |
|
444 | ||
445 | common_start_datetime_utc = start_datetime_utc |
|
446 | common_end_datetime_utc = end_datetime_utc |
|
447 | ||
448 | print("Getting common time slot of energy values for all meters") |
|
449 | if energy_meter_hourly is not None and len(energy_meter_hourly) > 0: |
|
450 | for meter_id, energy_hourly in energy_meter_hourly.items(): |
|
451 | if energy_hourly is None or len(energy_hourly) == 0: |
|
452 | common_start_datetime_utc = None |
|
453 | common_end_datetime_utc = None |
|
454 | break |
|
455 | else: |
|
456 | if common_start_datetime_utc < min(energy_hourly.keys()): |
|
457 | common_start_datetime_utc = min(energy_hourly.keys()) |
|
458 | if common_end_datetime_utc > max(energy_hourly.keys()): |
|
459 | common_end_datetime_utc = max(energy_hourly.keys()) |
|
460 | ||
461 | print("Getting common time slot of energy values for all virtual meters") |
|
462 | if common_start_datetime_utc is not None and common_start_datetime_utc is not None: |
|
463 | if energy_virtual_meter_hourly is not None and len(energy_virtual_meter_hourly) > 0: |
|
464 | for meter_id, energy_hourly in energy_virtual_meter_hourly.items(): |
|
465 | if energy_hourly is None or len(energy_hourly) == 0: |
|
466 | common_start_datetime_utc = None |
|
467 | common_end_datetime_utc = None |
|
468 | break |
|
469 | else: |
|
470 | if common_start_datetime_utc < min(energy_hourly.keys()): |
|
471 | common_start_datetime_utc = min(energy_hourly.keys()) |
|
472 | if common_end_datetime_utc > max(energy_hourly.keys()): |
|
473 | common_end_datetime_utc = max(energy_hourly.keys()) |
|
474 | ||
475 | print("Getting common time slot of energy values for all offline meters") |
|
476 | if common_start_datetime_utc is not None and common_start_datetime_utc is not None: |
|
477 | if energy_offline_meter_hourly is not None and len(energy_offline_meter_hourly) > 0: |
|
478 | for meter_id, energy_hourly in energy_offline_meter_hourly.items(): |
|
479 | if energy_hourly is None or len(energy_hourly) == 0: |
|
480 | common_start_datetime_utc = None |
|
481 | common_end_datetime_utc = None |
|
482 | break |
|
483 | else: |
|
484 | if common_start_datetime_utc < min(energy_hourly.keys()): |
|
485 | common_start_datetime_utc = min(energy_hourly.keys()) |
|
486 | if common_end_datetime_utc > max(energy_hourly.keys()): |
|
487 | common_end_datetime_utc = max(energy_hourly.keys()) |
|
488 | ||
489 | print("Getting common time slot of energy values for all equipments...") |
|
490 | if common_start_datetime_utc is not None and common_start_datetime_utc is not None: |
|
491 | if energy_equipment_hourly is not None and len(energy_equipment_hourly) > 0: |
|
492 | for equipment_id, energy_hourly in energy_equipment_hourly.items(): |
|
493 | if energy_hourly is None or len(energy_hourly) == 0: |
|
494 | common_start_datetime_utc = None |
|
495 | common_end_datetime_utc = None |
|
496 | break |
|
497 | else: |
|
498 | if common_start_datetime_utc < min(energy_hourly.keys()): |
|
499 | common_start_datetime_utc = min(energy_hourly.keys()) |
|
500 | if common_end_datetime_utc > max(energy_hourly.keys()): |
|
501 | common_end_datetime_utc = max(energy_hourly.keys()) |
|
502 | ||
503 | if (energy_meter_hourly is None or len(energy_meter_hourly) == 0) and \ |
|
504 | (energy_virtual_meter_hourly is None or len(energy_virtual_meter_hourly) == 0) and \ |
|
505 | (energy_offline_meter_hourly is None or len(energy_offline_meter_hourly) == 0) and \ |
|
506 | (energy_equipment_hourly is None or len(energy_equipment_hourly) == 0): |
|
507 | # There isn't any energy data |
|
508 | print("There isn't any energy data") |
|
509 | # continue the for combined equipment loop to the next combined equipment |
|
510 | print("continue the for combined equipment loop to the next combined equipment") |
|
511 | if cursor_energy_db: |
|
512 | cursor_energy_db.close() |
|
513 | if cnx_energy_db: |
|
514 | cnx_energy_db.close() |
|
515 | return None |
|
516 | ||
517 | print("common_start_datetime_utc: " + str(common_start_datetime_utc)) |
|
518 | print("common_end_datetime_utc: " + str(common_end_datetime_utc)) |
|
519 | ||
520 | #################################################################################################################### |
|
521 | # Step 11: aggregate energy data in the common time slot by energy categories and hourly |
|
522 | #################################################################################################################### |
|
523 | ||
524 | print("Step 11: aggregate energy data in the common time slot by energy categories and hourly") |
|
525 | aggregated_values = list() |
|
526 | try: |
|
527 | current_datetime_utc = common_start_datetime_utc |
|
528 | while common_start_datetime_utc is not None \ |
|
529 | and common_end_datetime_utc is not None \ |
|
530 | and current_datetime_utc <= common_end_datetime_utc: |
|
531 | aggregated_value = dict() |
|
532 | aggregated_value['start_datetime_utc'] = current_datetime_utc |
|
533 | aggregated_value['meta_data'] = dict() |
|
534 | ||
535 | if meter_list is not None and len(meter_list) > 0: |
|
536 | for meter in meter_list: |
|
537 | meter_id = str(meter['id']) |
|
538 | energy_category_id = meter['energy_category_id'] |
|
539 | actual_value = energy_meter_hourly[meter_id].get(current_datetime_utc, Decimal(0.0)) |
|
540 | aggregated_value['meta_data'][energy_category_id] = \ |
|
541 | aggregated_value['meta_data'].get(energy_category_id, Decimal(0.0)) + actual_value |
|
542 | ||
543 | if virtual_meter_list is not None and len(virtual_meter_list) > 0: |
|
544 | for virtual_meter in virtual_meter_list: |
|
545 | virtual_meter_id = str(virtual_meter['id']) |
|
546 | energy_category_id = virtual_meter['energy_category_id'] |
|
547 | actual_value = energy_virtual_meter_hourly[virtual_meter_id].get(current_datetime_utc, Decimal(0.0)) |
|
548 | aggregated_value['meta_data'][energy_category_id] = \ |
|
549 | aggregated_value['meta_data'].get(energy_category_id, Decimal(0.0)) + actual_value |
|
550 | ||
551 | if offline_meter_list is not None and len(offline_meter_list) > 0: |
|
552 | for offline_meter in offline_meter_list: |
|
553 | offline_meter_id = str(offline_meter['id']) |
|
554 | energy_category_id = offline_meter['energy_category_id'] |
|
555 | actual_value = energy_offline_meter_hourly[offline_meter_id].get(current_datetime_utc, Decimal(0.0)) |
|
556 | aggregated_value['meta_data'][energy_category_id] = \ |
|
557 | aggregated_value['meta_data'].get(energy_category_id, Decimal(0.0)) + actual_value |
|
558 | ||
559 | if equipment_list is not None and len(equipment_list) > 0: |
|
560 | for equipment in equipment_list: |
|
561 | equipment_id = str(equipment['id']) |
|
562 | meta_data_dict = energy_equipment_hourly[equipment_id].get(current_datetime_utc, None) |
|
563 | if meta_data_dict is not None and len(meta_data_dict) > 0: |
|
564 | for energy_category_id, actual_value in meta_data_dict.items(): |
|
565 | aggregated_value['meta_data'][energy_category_id] = \ |
|
566 | aggregated_value['meta_data'].get(energy_category_id, Decimal(0.0)) + actual_value |
|
567 | ||
568 | aggregated_values.append(aggregated_value) |
|
569 | ||
570 | current_datetime_utc += timedelta(minutes=config.minutes_to_count) |
|
571 | ||
572 | except Exception as e: |
|
573 | error_string = "Error in step 11 of combined_equipment_energy_input_category.worker " + str(e) |
|
574 | if cursor_energy_db: |
|
575 | cursor_energy_db.close() |
|
576 | if cnx_energy_db: |
|
577 | cnx_energy_db.close() |
|
578 | print(error_string) |
|
579 | return error_string |
|
580 | ||
581 | #################################################################################################################### |
|
582 | # Step 12: save energy data to energy database |
|
583 | #################################################################################################################### |
|
584 | print("Step 12: save energy data to energy database") |
|
585 | ||
586 | if len(aggregated_values) > 0: |
|
587 | try: |
|
588 | add_values = (" INSERT INTO tbl_combined_equipment_input_category_hourly " |
|
589 | " (combined_equipment_id, " |
|
590 | " energy_category_id, " |
|
591 | " start_datetime_utc, " |
|
592 | " actual_value) " |
|
593 | " VALUES ") |
|
594 | ||
595 | for aggregated_value in aggregated_values: |
|
596 | for energy_category_id, actual_value in aggregated_value['meta_data'].items(): |
|
597 | add_values += " (" + str(combined_equipment['id']) + "," |
|
598 | add_values += " " + str(energy_category_id) + "," |
|
599 | add_values += "'" + aggregated_value['start_datetime_utc'].isoformat()[0:19] + "'," |
|
600 | add_values += str(actual_value) + "), " |
|
601 | print("add_values:" + add_values) |
|
602 | # trim ", " at the end of string and then execute |
|
603 | cursor_energy_db.execute(add_values[:-2]) |
|
604 | cnx_energy_db.commit() |
|
605 | ||
606 | except Exception as e: |
|
607 | error_string = "Error in step 12.1 of combined_equipment_energy_input_category.worker " + str(e) |
|
608 | print(error_string) |
|
609 | return error_string |
|
610 | finally: |
|
611 | if cursor_energy_db: |
|
612 | cursor_energy_db.close() |
|
613 | if cnx_energy_db: |
|
614 | cnx_energy_db.close() |
|
615 | else: |
|
616 | if cursor_energy_db: |
|
617 | cursor_energy_db.close() |
|
618 | if cnx_energy_db: |
|
619 | cnx_energy_db.close() |
|
620 |
@@ 108-618 (lines=511) @@ | ||
105 | # NOTE: returns None or the error string because that the logger object cannot be passed in as parameter |
|
106 | ######################################################################################################################## |
|
107 | ||
108 | def worker(shopfloor): |
|
109 | #################################################################################################################### |
|
110 | # Step 1: get all input meters associated with the shopfloor |
|
111 | #################################################################################################################### |
|
112 | print("Step 1: get all input meters associated with the shopfloor " + str(shopfloor['name'])) |
|
113 | ||
114 | meter_list = list() |
|
115 | cnx_system_db = None |
|
116 | cursor_system_db = None |
|
117 | try: |
|
118 | cnx_system_db = mysql.connector.connect(**config.myems_system_db) |
|
119 | cursor_system_db = cnx_system_db.cursor() |
|
120 | except Exception as e: |
|
121 | error_string = "Error in step 1.1 of shopfloor_energy_input_item.worker " + str(e) |
|
122 | if cursor_system_db: |
|
123 | cursor_system_db.close() |
|
124 | if cnx_system_db: |
|
125 | cnx_system_db.close() |
|
126 | print(error_string) |
|
127 | return error_string |
|
128 | ||
129 | try: |
|
130 | cursor_system_db.execute(" SELECT m.id, m.name, m.energy_item_id " |
|
131 | " FROM tbl_meters m, tbl_shopfloors_meters tm " |
|
132 | " WHERE m.id = tm.meter_id " |
|
133 | " AND m.is_counted = true " |
|
134 | " AND m.energy_item_id is NOT NULL " |
|
135 | " AND tm.shopfloor_id = %s ", |
|
136 | (shopfloor['id'],)) |
|
137 | rows_meters = cursor_system_db.fetchall() |
|
138 | ||
139 | if rows_meters is not None and len(rows_meters) > 0: |
|
140 | for row in rows_meters: |
|
141 | meter_list.append({"id": row[0], |
|
142 | "name": row[1], |
|
143 | "energy_item_id": row[2]}) |
|
144 | ||
145 | except Exception as e: |
|
146 | error_string = "Error in step 1.2 of shopfloor_energy_input_item.worker " + str(e) |
|
147 | if cursor_system_db: |
|
148 | cursor_system_db.close() |
|
149 | if cnx_system_db: |
|
150 | cnx_system_db.close() |
|
151 | print(error_string) |
|
152 | return error_string |
|
153 | ||
154 | #################################################################################################################### |
|
155 | # Step 2: get all input virtual meters associated with the shopfloor |
|
156 | #################################################################################################################### |
|
157 | print("Step 2: get all input virtual meters associated with the shopfloor") |
|
158 | virtual_meter_list = list() |
|
159 | ||
160 | try: |
|
161 | cursor_system_db.execute(" SELECT m.id, m.name, m.energy_item_id " |
|
162 | " FROM tbl_virtual_meters m, tbl_shopfloors_virtual_meters tm " |
|
163 | " WHERE m.id = tm.virtual_meter_id " |
|
164 | " AND m.energy_item_id is NOT NULL " |
|
165 | " AND m.is_counted = true " |
|
166 | " AND tm.shopfloor_id = %s ", |
|
167 | (shopfloor['id'],)) |
|
168 | rows_virtual_meters = cursor_system_db.fetchall() |
|
169 | ||
170 | if rows_virtual_meters is not None and len(rows_virtual_meters) > 0: |
|
171 | for row in rows_virtual_meters: |
|
172 | virtual_meter_list.append({"id": row[0], |
|
173 | "name": row[1], |
|
174 | "energy_item_id": row[2]}) |
|
175 | ||
176 | except Exception as e: |
|
177 | error_string = "Error in step 2.1 of shopfloor_energy_input_item.worker " + str(e) |
|
178 | if cursor_system_db: |
|
179 | cursor_system_db.close() |
|
180 | if cnx_system_db: |
|
181 | cnx_system_db.close() |
|
182 | print(error_string) |
|
183 | return error_string |
|
184 | ||
185 | #################################################################################################################### |
|
186 | # Step 3: get all input offline meters associated with the shopfloor |
|
187 | #################################################################################################################### |
|
188 | print("Step 3: get all input offline meters associated with the shopfloor") |
|
189 | ||
190 | offline_meter_list = list() |
|
191 | ||
192 | try: |
|
193 | cursor_system_db.execute(" SELECT m.id, m.name, m.energy_item_id " |
|
194 | " FROM tbl_offline_meters m, tbl_shopfloors_offline_meters tm " |
|
195 | " WHERE m.id = tm.offline_meter_id " |
|
196 | " AND m.energy_item_id is NOT NULL " |
|
197 | " AND m.is_counted = true " |
|
198 | " AND tm.shopfloor_id = %s ", |
|
199 | (shopfloor['id'],)) |
|
200 | rows_offline_meters = cursor_system_db.fetchall() |
|
201 | ||
202 | if rows_offline_meters is not None and len(rows_offline_meters) > 0: |
|
203 | for row in rows_offline_meters: |
|
204 | offline_meter_list.append({"id": row[0], |
|
205 | "name": row[1], |
|
206 | "energy_item_id": row[2]}) |
|
207 | ||
208 | except Exception as e: |
|
209 | error_string = "Error in step 3.1 of shopfloor_energy_input_item.worker " + str(e) |
|
210 | if cursor_system_db: |
|
211 | cursor_system_db.close() |
|
212 | if cnx_system_db: |
|
213 | cnx_system_db.close() |
|
214 | print(error_string) |
|
215 | return error_string |
|
216 | ||
217 | #################################################################################################################### |
|
218 | # Step 4: get all equipments associated with the shopfloor |
|
219 | #################################################################################################################### |
|
220 | print("Step 4: get all equipments associated with the shopfloor") |
|
221 | ||
222 | equipment_list = list() |
|
223 | ||
224 | try: |
|
225 | cursor_system_db.execute(" SELECT e.id, e.name " |
|
226 | " FROM tbl_equipments e, tbl_shopfloors_equipments se " |
|
227 | " WHERE e.id = se.equipment_id " |
|
228 | " AND e.is_input_counted = true " |
|
229 | " AND se.shopfloor_id = %s ", |
|
230 | (shopfloor['id'],)) |
|
231 | rows_equipments = cursor_system_db.fetchall() |
|
232 | ||
233 | if rows_equipments is not None and len(rows_equipments) > 0: |
|
234 | for row in rows_equipments: |
|
235 | equipment_list.append({"id": row[0], |
|
236 | "name": row[1]}) |
|
237 | ||
238 | except Exception as e: |
|
239 | error_string = "Error in step 4 of shopfloor_energy_input_item.worker " + str(e) |
|
240 | print(error_string) |
|
241 | return error_string |
|
242 | finally: |
|
243 | if cursor_system_db: |
|
244 | cursor_system_db.close() |
|
245 | if cnx_system_db: |
|
246 | cnx_system_db.close() |
|
247 | ||
248 | #################################################################################################################### |
|
249 | # stop to the next shopfloor if this shopfloor is empty |
|
250 | #################################################################################################################### |
|
251 | if (meter_list is None or len(meter_list) == 0) and \ |
|
252 | (virtual_meter_list is None or len(virtual_meter_list) == 0) and \ |
|
253 | (offline_meter_list is None or len(offline_meter_list) == 0) and \ |
|
254 | (equipment_list is None or len(equipment_list) == 0): |
|
255 | print("This is an empty shopfloor ") |
|
256 | return None |
|
257 | ||
258 | #################################################################################################################### |
|
259 | # Step 5: determine start datetime and end datetime to aggregate |
|
260 | #################################################################################################################### |
|
261 | print("Step 5: determine start datetime and end datetime to aggregate") |
|
262 | cnx_energy_db = None |
|
263 | cursor_energy_db = None |
|
264 | try: |
|
265 | cnx_energy_db = mysql.connector.connect(**config.myems_energy_db) |
|
266 | cursor_energy_db = cnx_energy_db.cursor() |
|
267 | except Exception as e: |
|
268 | error_string = "Error in step 5.1 of shopfloor_energy_input_item.worker " + str(e) |
|
269 | if cursor_energy_db: |
|
270 | cursor_energy_db.close() |
|
271 | if cnx_energy_db: |
|
272 | cnx_energy_db.close() |
|
273 | print(error_string) |
|
274 | return error_string |
|
275 | ||
276 | try: |
|
277 | query = (" SELECT MAX(start_datetime_utc) " |
|
278 | " FROM tbl_shopfloor_input_item_hourly " |
|
279 | " WHERE shopfloor_id = %s ") |
|
280 | cursor_energy_db.execute(query, (shopfloor['id'],)) |
|
281 | row_datetime = cursor_energy_db.fetchone() |
|
282 | start_datetime_utc = datetime.strptime(config.start_datetime_utc, '%Y-%m-%d %H:%M:%S') |
|
283 | start_datetime_utc = start_datetime_utc.replace(minute=0, second=0, microsecond=0, tzinfo=None) |
|
284 | ||
285 | if row_datetime is not None and len(row_datetime) > 0 and isinstance(row_datetime[0], datetime): |
|
286 | # replace second and microsecond with 0 |
|
287 | # note: do not replace minute in case of calculating in half hourly |
|
288 | start_datetime_utc = row_datetime[0].replace(second=0, microsecond=0, tzinfo=None) |
|
289 | # start from the next time slot |
|
290 | start_datetime_utc += timedelta(minutes=config.minutes_to_count) |
|
291 | ||
292 | end_datetime_utc = datetime.utcnow().replace(second=0, microsecond=0, tzinfo=None) |
|
293 | ||
294 | print("start_datetime_utc: " + start_datetime_utc.isoformat()[0:19] |
|
295 | + "end_datetime_utc: " + end_datetime_utc.isoformat()[0:19]) |
|
296 | ||
297 | except Exception as e: |
|
298 | error_string = "Error in step 5.2 of shopfloor_energy_input_item.worker " + str(e) |
|
299 | if cursor_energy_db: |
|
300 | cursor_energy_db.close() |
|
301 | if cnx_energy_db: |
|
302 | cnx_energy_db.close() |
|
303 | print(error_string) |
|
304 | return error_string |
|
305 | ||
306 | #################################################################################################################### |
|
307 | # Step 6: for each meter in list, get energy input data from energy database |
|
308 | #################################################################################################################### |
|
309 | energy_meter_hourly = dict() |
|
310 | try: |
|
311 | if meter_list is not None and len(meter_list) > 0: |
|
312 | for meter in meter_list: |
|
313 | meter_id = str(meter['id']) |
|
314 | ||
315 | query = (" SELECT start_datetime_utc, actual_value " |
|
316 | " FROM tbl_meter_hourly " |
|
317 | " WHERE meter_id = %s " |
|
318 | " AND start_datetime_utc >= %s " |
|
319 | " AND start_datetime_utc < %s " |
|
320 | " ORDER BY start_datetime_utc ") |
|
321 | cursor_energy_db.execute(query, (meter_id, start_datetime_utc, end_datetime_utc,)) |
|
322 | rows_energy_values = cursor_energy_db.fetchall() |
|
323 | if rows_energy_values is None or len(rows_energy_values) == 0: |
|
324 | energy_meter_hourly[meter_id] = None |
|
325 | else: |
|
326 | energy_meter_hourly[meter_id] = dict() |
|
327 | for row_energy_value in rows_energy_values: |
|
328 | energy_meter_hourly[meter_id][row_energy_value[0]] = row_energy_value[1] |
|
329 | except Exception as e: |
|
330 | error_string = "Error in step 6.1 of shopfloor_energy_input_item.worker " + str(e) |
|
331 | if cursor_energy_db: |
|
332 | cursor_energy_db.close() |
|
333 | if cnx_energy_db: |
|
334 | cnx_energy_db.close() |
|
335 | print(error_string) |
|
336 | return error_string |
|
337 | ||
338 | #################################################################################################################### |
|
339 | # Step 7: for each virtual meter in list, get energy input data from energy database |
|
340 | #################################################################################################################### |
|
341 | energy_virtual_meter_hourly = dict() |
|
342 | if virtual_meter_list is not None and len(virtual_meter_list) > 0: |
|
343 | try: |
|
344 | for virtual_meter in virtual_meter_list: |
|
345 | virtual_meter_id = str(virtual_meter['id']) |
|
346 | ||
347 | query = (" SELECT start_datetime_utc, actual_value " |
|
348 | " FROM tbl_virtual_meter_hourly " |
|
349 | " WHERE virtual_meter_id = %s " |
|
350 | " AND start_datetime_utc >= %s " |
|
351 | " AND start_datetime_utc < %s " |
|
352 | " ORDER BY start_datetime_utc ") |
|
353 | cursor_energy_db.execute(query, (virtual_meter_id, start_datetime_utc, end_datetime_utc,)) |
|
354 | rows_energy_values = cursor_energy_db.fetchall() |
|
355 | if rows_energy_values is None or len(rows_energy_values) == 0: |
|
356 | energy_virtual_meter_hourly[virtual_meter_id] = None |
|
357 | else: |
|
358 | energy_virtual_meter_hourly[virtual_meter_id] = dict() |
|
359 | for row_energy_value in rows_energy_values: |
|
360 | energy_virtual_meter_hourly[virtual_meter_id][row_energy_value[0]] = row_energy_value[1] |
|
361 | except Exception as e: |
|
362 | error_string = "Error in step 7.1 of shopfloor_energy_input_item.worker " + str(e) |
|
363 | if cursor_energy_db: |
|
364 | cursor_energy_db.close() |
|
365 | if cnx_energy_db: |
|
366 | cnx_energy_db.close() |
|
367 | print(error_string) |
|
368 | return error_string |
|
369 | ||
370 | #################################################################################################################### |
|
371 | # Step 8: for each offline meter in list, get energy input data from energy database |
|
372 | #################################################################################################################### |
|
373 | energy_offline_meter_hourly = dict() |
|
374 | if offline_meter_list is not None and len(offline_meter_list) > 0: |
|
375 | try: |
|
376 | for offline_meter in offline_meter_list: |
|
377 | offline_meter_id = str(offline_meter['id']) |
|
378 | ||
379 | query = (" SELECT start_datetime_utc, actual_value " |
|
380 | " FROM tbl_offline_meter_hourly " |
|
381 | " WHERE offline_meter_id = %s " |
|
382 | " AND start_datetime_utc >= %s " |
|
383 | " AND start_datetime_utc < %s " |
|
384 | " ORDER BY start_datetime_utc ") |
|
385 | cursor_energy_db.execute(query, (offline_meter_id, start_datetime_utc, end_datetime_utc,)) |
|
386 | rows_energy_values = cursor_energy_db.fetchall() |
|
387 | if rows_energy_values is None or len(rows_energy_values) == 0: |
|
388 | energy_offline_meter_hourly[offline_meter_id] = None |
|
389 | else: |
|
390 | energy_offline_meter_hourly[offline_meter_id] = dict() |
|
391 | for row_energy_value in rows_energy_values: |
|
392 | energy_offline_meter_hourly[offline_meter_id][row_energy_value[0]] = row_energy_value[1] |
|
393 | ||
394 | except Exception as e: |
|
395 | error_string = "Error in step 8.1 of shopfloor_energy_input_item.worker " + str(e) |
|
396 | if cursor_energy_db: |
|
397 | cursor_energy_db.close() |
|
398 | if cnx_energy_db: |
|
399 | cnx_energy_db.close() |
|
400 | print(error_string) |
|
401 | return error_string |
|
402 | ||
403 | #################################################################################################################### |
|
404 | # Step 9: for each equipment in list, get energy input data from energy database |
|
405 | #################################################################################################################### |
|
406 | energy_equipment_hourly = dict() |
|
407 | if equipment_list is not None and len(equipment_list) > 0: |
|
408 | try: |
|
409 | for equipment in equipment_list: |
|
410 | equipment_id = str(equipment['id']) |
|
411 | query = (" SELECT start_datetime_utc, energy_item_id, actual_value " |
|
412 | " FROM tbl_equipment_input_item_hourly " |
|
413 | " WHERE equipment_id = %s " |
|
414 | " AND start_datetime_utc >= %s " |
|
415 | " AND start_datetime_utc < %s " |
|
416 | " ORDER BY start_datetime_utc ") |
|
417 | cursor_energy_db.execute(query, (equipment_id, start_datetime_utc, end_datetime_utc,)) |
|
418 | rows_energy_values = cursor_energy_db.fetchall() |
|
419 | if rows_energy_values is None or len(rows_energy_values) == 0: |
|
420 | energy_equipment_hourly[equipment_id] = None |
|
421 | else: |
|
422 | energy_equipment_hourly[equipment_id] = dict() |
|
423 | for row_value in rows_energy_values: |
|
424 | current_datetime_utc = row_value[0] |
|
425 | if current_datetime_utc not in energy_equipment_hourly[equipment_id]: |
|
426 | energy_equipment_hourly[equipment_id][current_datetime_utc] = dict() |
|
427 | energy_item_id = row_value[1] |
|
428 | actual_value = row_value[2] |
|
429 | energy_equipment_hourly[equipment_id][current_datetime_utc][energy_item_id] = \ |
|
430 | actual_value |
|
431 | except Exception as e: |
|
432 | error_string = "Error in step 9 of shopfloor_energy_input_item.worker " + str(e) |
|
433 | if cursor_energy_db: |
|
434 | cursor_energy_db.close() |
|
435 | if cnx_energy_db: |
|
436 | cnx_energy_db.close() |
|
437 | print(error_string) |
|
438 | return error_string |
|
439 | ||
440 | #################################################################################################################### |
|
441 | # Step 10: determine common time slot to aggregate |
|
442 | #################################################################################################################### |
|
443 | ||
444 | common_start_datetime_utc = start_datetime_utc |
|
445 | common_end_datetime_utc = end_datetime_utc |
|
446 | ||
447 | print("Getting common time slot of energy values for all meters") |
|
448 | if energy_meter_hourly is not None and len(energy_meter_hourly) > 0: |
|
449 | for meter_id, energy_hourly in energy_meter_hourly.items(): |
|
450 | if energy_hourly is None or len(energy_hourly) == 0: |
|
451 | common_start_datetime_utc = None |
|
452 | common_end_datetime_utc = None |
|
453 | break |
|
454 | else: |
|
455 | if common_start_datetime_utc < min(energy_hourly.keys()): |
|
456 | common_start_datetime_utc = min(energy_hourly.keys()) |
|
457 | if common_end_datetime_utc > max(energy_hourly.keys()): |
|
458 | common_end_datetime_utc = max(energy_hourly.keys()) |
|
459 | ||
460 | print("Getting common time slot of energy values for all virtual meters") |
|
461 | if common_start_datetime_utc is not None and common_start_datetime_utc is not None: |
|
462 | if energy_virtual_meter_hourly is not None and len(energy_virtual_meter_hourly) > 0: |
|
463 | for meter_id, energy_hourly in energy_virtual_meter_hourly.items(): |
|
464 | if energy_hourly is None or len(energy_hourly) == 0: |
|
465 | common_start_datetime_utc = None |
|
466 | common_end_datetime_utc = None |
|
467 | break |
|
468 | else: |
|
469 | if common_start_datetime_utc < min(energy_hourly.keys()): |
|
470 | common_start_datetime_utc = min(energy_hourly.keys()) |
|
471 | if common_end_datetime_utc > max(energy_hourly.keys()): |
|
472 | common_end_datetime_utc = max(energy_hourly.keys()) |
|
473 | ||
474 | print("Getting common time slot of energy values for all offline meters") |
|
475 | if common_start_datetime_utc is not None and common_start_datetime_utc is not None: |
|
476 | if energy_offline_meter_hourly is not None and len(energy_offline_meter_hourly) > 0: |
|
477 | for meter_id, energy_hourly in energy_offline_meter_hourly.items(): |
|
478 | if energy_hourly is None or len(energy_hourly) == 0: |
|
479 | common_start_datetime_utc = None |
|
480 | common_end_datetime_utc = None |
|
481 | break |
|
482 | else: |
|
483 | if common_start_datetime_utc < min(energy_hourly.keys()): |
|
484 | common_start_datetime_utc = min(energy_hourly.keys()) |
|
485 | if common_end_datetime_utc > max(energy_hourly.keys()): |
|
486 | common_end_datetime_utc = max(energy_hourly.keys()) |
|
487 | ||
488 | print("Getting common time slot of energy values for all equipments...") |
|
489 | if common_start_datetime_utc is not None and common_start_datetime_utc is not None: |
|
490 | if energy_equipment_hourly is not None and len(energy_equipment_hourly) > 0: |
|
491 | for equipment_id, energy_hourly in energy_equipment_hourly.items(): |
|
492 | if energy_hourly is None or len(energy_hourly) == 0: |
|
493 | common_start_datetime_utc = None |
|
494 | common_end_datetime_utc = None |
|
495 | break |
|
496 | else: |
|
497 | if common_start_datetime_utc < min(energy_hourly.keys()): |
|
498 | common_start_datetime_utc = min(energy_hourly.keys()) |
|
499 | if common_end_datetime_utc > max(energy_hourly.keys()): |
|
500 | common_end_datetime_utc = max(energy_hourly.keys()) |
|
501 | ||
502 | if (energy_meter_hourly is None or len(energy_meter_hourly) == 0) and \ |
|
503 | (energy_virtual_meter_hourly is None or len(energy_virtual_meter_hourly) == 0) and \ |
|
504 | (energy_offline_meter_hourly is None or len(energy_offline_meter_hourly) == 0) and \ |
|
505 | (energy_equipment_hourly is None or len(energy_equipment_hourly) == 0): |
|
506 | # There isn't any energy data |
|
507 | print("There isn't any energy data") |
|
508 | # continue the for shopfloor loop to the next shopfloor |
|
509 | print("continue the for shopfloor loop to the next shopfloor") |
|
510 | if cursor_energy_db: |
|
511 | cursor_energy_db.close() |
|
512 | if cnx_energy_db: |
|
513 | cnx_energy_db.close() |
|
514 | return None |
|
515 | ||
516 | print("common_start_datetime_utc: " + str(common_start_datetime_utc)) |
|
517 | print("common_end_datetime_utc: " + str(common_end_datetime_utc)) |
|
518 | ||
519 | #################################################################################################################### |
|
520 | # Step 11: aggregate energy data in the common time slot by energy items and hourly |
|
521 | #################################################################################################################### |
|
522 | ||
523 | print("Step 11: aggregate energy data in the common time slot by energy items and hourly") |
|
524 | aggregated_values = list() |
|
525 | try: |
|
526 | current_datetime_utc = common_start_datetime_utc |
|
527 | while common_start_datetime_utc is not None \ |
|
528 | and common_end_datetime_utc is not None \ |
|
529 | and current_datetime_utc <= common_end_datetime_utc: |
|
530 | aggregated_value = dict() |
|
531 | aggregated_value['start_datetime_utc'] = current_datetime_utc |
|
532 | aggregated_value['meta_data'] = dict() |
|
533 | ||
534 | if meter_list is not None and len(meter_list) > 0: |
|
535 | for meter in meter_list: |
|
536 | meter_id = str(meter['id']) |
|
537 | energy_item_id = meter['energy_item_id'] |
|
538 | actual_value = energy_meter_hourly[meter_id].get(current_datetime_utc, Decimal(0.0)) |
|
539 | aggregated_value['meta_data'][energy_item_id] = \ |
|
540 | aggregated_value['meta_data'].get(energy_item_id, Decimal(0.0)) + actual_value |
|
541 | ||
542 | if virtual_meter_list is not None and len(virtual_meter_list) > 0: |
|
543 | for virtual_meter in virtual_meter_list: |
|
544 | virtual_meter_id = str(virtual_meter['id']) |
|
545 | energy_item_id = virtual_meter['energy_item_id'] |
|
546 | actual_value = energy_virtual_meter_hourly[virtual_meter_id].get(current_datetime_utc, Decimal(0.0)) |
|
547 | aggregated_value['meta_data'][energy_item_id] = \ |
|
548 | aggregated_value['meta_data'].get(energy_item_id, Decimal(0.0)) + actual_value |
|
549 | ||
550 | if offline_meter_list is not None and len(offline_meter_list) > 0: |
|
551 | for offline_meter in offline_meter_list: |
|
552 | offline_meter_id = str(offline_meter['id']) |
|
553 | energy_item_id = offline_meter['energy_item_id'] |
|
554 | actual_value = energy_offline_meter_hourly[offline_meter_id].get(current_datetime_utc, Decimal(0.0)) |
|
555 | aggregated_value['meta_data'][energy_item_id] = \ |
|
556 | aggregated_value['meta_data'].get(energy_item_id, Decimal(0.0)) + actual_value |
|
557 | ||
558 | if equipment_list is not None and len(equipment_list) > 0: |
|
559 | for equipment in equipment_list: |
|
560 | equipment_id = str(equipment['id']) |
|
561 | meta_data_dict = energy_equipment_hourly[equipment_id].get(current_datetime_utc, None) |
|
562 | if meta_data_dict is not None and len(meta_data_dict) > 0: |
|
563 | for energy_item_id, actual_value in meta_data_dict.items(): |
|
564 | aggregated_value['meta_data'][energy_item_id] = \ |
|
565 | aggregated_value['meta_data'].get(energy_item_id, Decimal(0.0)) + actual_value |
|
566 | ||
567 | aggregated_values.append(aggregated_value) |
|
568 | ||
569 | current_datetime_utc += timedelta(minutes=config.minutes_to_count) |
|
570 | ||
571 | except Exception as e: |
|
572 | error_string = "Error in step 11 of shopfloor_energy_input_item.worker " + str(e) |
|
573 | if cursor_energy_db: |
|
574 | cursor_energy_db.close() |
|
575 | if cnx_energy_db: |
|
576 | cnx_energy_db.close() |
|
577 | print(error_string) |
|
578 | return error_string |
|
579 | ||
580 | #################################################################################################################### |
|
581 | # Step 12: save energy data to energy database |
|
582 | #################################################################################################################### |
|
583 | print("Step 12: save energy data to energy database") |
|
584 | ||
585 | if len(aggregated_values) > 0: |
|
586 | try: |
|
587 | add_values = (" INSERT INTO tbl_shopfloor_input_item_hourly " |
|
588 | " (shopfloor_id, " |
|
589 | " energy_item_id, " |
|
590 | " start_datetime_utc, " |
|
591 | " actual_value) " |
|
592 | " VALUES ") |
|
593 | ||
594 | for aggregated_value in aggregated_values: |
|
595 | for energy_item_id, actual_value in aggregated_value['meta_data'].items(): |
|
596 | add_values += " (" + str(shopfloor['id']) + "," |
|
597 | add_values += " " + str(energy_item_id) + "," |
|
598 | add_values += "'" + aggregated_value['start_datetime_utc'].isoformat()[0:19] + "'," |
|
599 | add_values += str(actual_value) + "), " |
|
600 | print("add_values:" + add_values) |
|
601 | # trim ", " at the end of string and then execute |
|
602 | cursor_energy_db.execute(add_values[:-2]) |
|
603 | cnx_energy_db.commit() |
|
604 | ||
605 | except Exception as e: |
|
606 | error_string = "Error in step 12.1 of shopfloor_energy_input_item.worker " + str(e) |
|
607 | print(error_string) |
|
608 | return error_string |
|
609 | finally: |
|
610 | if cursor_energy_db: |
|
611 | cursor_energy_db.close() |
|
612 | if cnx_energy_db: |
|
613 | cnx_energy_db.close() |
|
614 | else: |
|
615 | if cursor_energy_db: |
|
616 | cursor_energy_db.close() |
|
617 | if cnx_energy_db: |
|
618 | cnx_energy_db.close() |
|
619 |
@@ 108-615 (lines=508) @@ | ||
105 | # NOTE: returns None or the error string because that the logger object cannot be passed in as parameter |
|
106 | ######################################################################################################################## |
|
107 | ||
108 | def worker(shopfloor): |
|
109 | #################################################################################################################### |
|
110 | # Step 1: get all input meters associated with the shopfloor |
|
111 | #################################################################################################################### |
|
112 | print("Step 1: get all input meters associated with the shopfloor " + str(shopfloor['name'])) |
|
113 | ||
114 | meter_list = list() |
|
115 | cnx_system_db = None |
|
116 | cursor_system_db = None |
|
117 | try: |
|
118 | cnx_system_db = mysql.connector.connect(**config.myems_system_db) |
|
119 | cursor_system_db = cnx_system_db.cursor() |
|
120 | except Exception as e: |
|
121 | error_string = "Error in step 1.1 of shopfloor_energy_input_category.worker " + str(e) |
|
122 | if cursor_system_db: |
|
123 | cursor_system_db.close() |
|
124 | if cnx_system_db: |
|
125 | cnx_system_db.close() |
|
126 | print(error_string) |
|
127 | return error_string |
|
128 | ||
129 | try: |
|
130 | cursor_system_db.execute(" SELECT m.id, m.name, m.energy_category_id " |
|
131 | " FROM tbl_meters m, tbl_shopfloors_meters tm " |
|
132 | " WHERE m.id = tm.meter_id " |
|
133 | " AND m.is_counted = true " |
|
134 | " AND tm.shopfloor_id = %s ", |
|
135 | (shopfloor['id'],)) |
|
136 | rows_meters = cursor_system_db.fetchall() |
|
137 | ||
138 | if rows_meters is not None and len(rows_meters) > 0: |
|
139 | for row in rows_meters: |
|
140 | meter_list.append({"id": row[0], |
|
141 | "name": row[1], |
|
142 | "energy_category_id": row[2]}) |
|
143 | ||
144 | except Exception as e: |
|
145 | error_string = "Error in step 1.2 of shopfloor_energy_input_category.worker " + str(e) |
|
146 | if cursor_system_db: |
|
147 | cursor_system_db.close() |
|
148 | if cnx_system_db: |
|
149 | cnx_system_db.close() |
|
150 | print(error_string) |
|
151 | return error_string |
|
152 | ||
153 | #################################################################################################################### |
|
154 | # Step 2: get all input virtual meters associated with the shopfloor |
|
155 | #################################################################################################################### |
|
156 | print("Step 2: get all input virtual meters associated with the shopfloor") |
|
157 | virtual_meter_list = list() |
|
158 | ||
159 | try: |
|
160 | cursor_system_db.execute(" SELECT m.id, m.name, m.energy_category_id " |
|
161 | " FROM tbl_virtual_meters m, tbl_shopfloors_virtual_meters tm " |
|
162 | " WHERE m.id = tm.virtual_meter_id " |
|
163 | " AND m.is_counted = true " |
|
164 | " AND tm.shopfloor_id = %s ", |
|
165 | (shopfloor['id'],)) |
|
166 | rows_virtual_meters = cursor_system_db.fetchall() |
|
167 | ||
168 | if rows_virtual_meters is not None and len(rows_virtual_meters) > 0: |
|
169 | for row in rows_virtual_meters: |
|
170 | virtual_meter_list.append({"id": row[0], |
|
171 | "name": row[1], |
|
172 | "energy_category_id": row[2]}) |
|
173 | ||
174 | except Exception as e: |
|
175 | error_string = "Error in step 2.1 of shopfloor_energy_input_category.worker " + str(e) |
|
176 | if cursor_system_db: |
|
177 | cursor_system_db.close() |
|
178 | if cnx_system_db: |
|
179 | cnx_system_db.close() |
|
180 | print(error_string) |
|
181 | return error_string |
|
182 | ||
183 | #################################################################################################################### |
|
184 | # Step 3: get all input offline meters associated with the shopfloor |
|
185 | #################################################################################################################### |
|
186 | print("Step 3: get all input offline meters associated with the shopfloor") |
|
187 | ||
188 | offline_meter_list = list() |
|
189 | ||
190 | try: |
|
191 | cursor_system_db.execute(" SELECT m.id, m.name, m.energy_category_id " |
|
192 | " FROM tbl_offline_meters m, tbl_shopfloors_offline_meters tm " |
|
193 | " WHERE m.id = tm.offline_meter_id " |
|
194 | " AND m.is_counted = true " |
|
195 | " AND tm.shopfloor_id = %s ", |
|
196 | (shopfloor['id'],)) |
|
197 | rows_offline_meters = cursor_system_db.fetchall() |
|
198 | ||
199 | if rows_offline_meters is not None and len(rows_offline_meters) > 0: |
|
200 | for row in rows_offline_meters: |
|
201 | offline_meter_list.append({"id": row[0], |
|
202 | "name": row[1], |
|
203 | "energy_category_id": row[2]}) |
|
204 | ||
205 | except Exception as e: |
|
206 | error_string = "Error in step 3.1 of shopfloor_energy_input_category.worker " + str(e) |
|
207 | if cursor_system_db: |
|
208 | cursor_system_db.close() |
|
209 | if cnx_system_db: |
|
210 | cnx_system_db.close() |
|
211 | print(error_string) |
|
212 | return error_string |
|
213 | ||
214 | #################################################################################################################### |
|
215 | # Step 4: get all equipments associated with the shopfloor |
|
216 | #################################################################################################################### |
|
217 | print("Step 4: get all equipments associated with the shopfloor") |
|
218 | ||
219 | equipment_list = list() |
|
220 | ||
221 | try: |
|
222 | cursor_system_db.execute(" SELECT e.id, e.name " |
|
223 | " FROM tbl_equipments e, tbl_shopfloors_equipments se " |
|
224 | " WHERE e.id = se.equipment_id " |
|
225 | " AND e.is_input_counted = true " |
|
226 | " AND se.shopfloor_id = %s ", |
|
227 | (shopfloor['id'],)) |
|
228 | rows_equipments = cursor_system_db.fetchall() |
|
229 | ||
230 | if rows_equipments is not None and len(rows_equipments) > 0: |
|
231 | for row in rows_equipments: |
|
232 | equipment_list.append({"id": row[0], |
|
233 | "name": row[1]}) |
|
234 | ||
235 | except Exception as e: |
|
236 | error_string = "Error in step 4 of shopfloor_energy_input_category.worker " + str(e) |
|
237 | print(error_string) |
|
238 | return error_string |
|
239 | finally: |
|
240 | if cursor_system_db: |
|
241 | cursor_system_db.close() |
|
242 | if cnx_system_db: |
|
243 | cnx_system_db.close() |
|
244 | ||
245 | #################################################################################################################### |
|
246 | # stop to the next shopfloor if this shopfloor is empty |
|
247 | #################################################################################################################### |
|
248 | if (meter_list is None or len(meter_list) == 0) and \ |
|
249 | (virtual_meter_list is None or len(virtual_meter_list) == 0) and \ |
|
250 | (offline_meter_list is None or len(offline_meter_list) == 0) and \ |
|
251 | (equipment_list is None or len(equipment_list) == 0): |
|
252 | print("This is an empty shopfloor ") |
|
253 | return None |
|
254 | ||
255 | #################################################################################################################### |
|
256 | # Step 5: determine start datetime and end datetime to aggregate |
|
257 | #################################################################################################################### |
|
258 | print("Step 5: determine start datetime and end datetime to aggregate") |
|
259 | cnx_energy_db = None |
|
260 | cursor_energy_db = None |
|
261 | try: |
|
262 | cnx_energy_db = mysql.connector.connect(**config.myems_energy_db) |
|
263 | cursor_energy_db = cnx_energy_db.cursor() |
|
264 | except Exception as e: |
|
265 | error_string = "Error in step 5.1 of shopfloor_energy_input_category.worker " + str(e) |
|
266 | if cursor_energy_db: |
|
267 | cursor_energy_db.close() |
|
268 | if cnx_energy_db: |
|
269 | cnx_energy_db.close() |
|
270 | print(error_string) |
|
271 | return error_string |
|
272 | ||
273 | try: |
|
274 | query = (" SELECT MAX(start_datetime_utc) " |
|
275 | " FROM tbl_shopfloor_input_category_hourly " |
|
276 | " WHERE shopfloor_id = %s ") |
|
277 | cursor_energy_db.execute(query, (shopfloor['id'],)) |
|
278 | row_datetime = cursor_energy_db.fetchone() |
|
279 | start_datetime_utc = datetime.strptime(config.start_datetime_utc, '%Y-%m-%d %H:%M:%S') |
|
280 | start_datetime_utc = start_datetime_utc.replace(minute=0, second=0, microsecond=0, tzinfo=None) |
|
281 | ||
282 | if row_datetime is not None and len(row_datetime) > 0 and isinstance(row_datetime[0], datetime): |
|
283 | # replace second and microsecond with 0 |
|
284 | # note: do not replace minute in case of calculating in half hourly |
|
285 | start_datetime_utc = row_datetime[0].replace(second=0, microsecond=0, tzinfo=None) |
|
286 | # start from the next time slot |
|
287 | start_datetime_utc += timedelta(minutes=config.minutes_to_count) |
|
288 | ||
289 | end_datetime_utc = datetime.utcnow().replace(second=0, microsecond=0, tzinfo=None) |
|
290 | ||
291 | print("start_datetime_utc: " + start_datetime_utc.isoformat()[0:19] |
|
292 | + "end_datetime_utc: " + end_datetime_utc.isoformat()[0:19]) |
|
293 | ||
294 | except Exception as e: |
|
295 | error_string = "Error in step 5.2 of shopfloor_energy_input_category.worker " + str(e) |
|
296 | if cursor_energy_db: |
|
297 | cursor_energy_db.close() |
|
298 | if cnx_energy_db: |
|
299 | cnx_energy_db.close() |
|
300 | print(error_string) |
|
301 | return error_string |
|
302 | ||
303 | #################################################################################################################### |
|
304 | # Step 6: for each meter in list, get energy input data from energy database |
|
305 | #################################################################################################################### |
|
306 | energy_meter_hourly = dict() |
|
307 | try: |
|
308 | if meter_list is not None and len(meter_list) > 0: |
|
309 | for meter in meter_list: |
|
310 | meter_id = str(meter['id']) |
|
311 | ||
312 | query = (" SELECT start_datetime_utc, actual_value " |
|
313 | " FROM tbl_meter_hourly " |
|
314 | " WHERE meter_id = %s " |
|
315 | " AND start_datetime_utc >= %s " |
|
316 | " AND start_datetime_utc < %s " |
|
317 | " ORDER BY start_datetime_utc ") |
|
318 | cursor_energy_db.execute(query, (meter_id, start_datetime_utc, end_datetime_utc,)) |
|
319 | rows_energy_values = cursor_energy_db.fetchall() |
|
320 | if rows_energy_values is None or len(rows_energy_values) == 0: |
|
321 | energy_meter_hourly[meter_id] = None |
|
322 | else: |
|
323 | energy_meter_hourly[meter_id] = dict() |
|
324 | for row_energy_value in rows_energy_values: |
|
325 | energy_meter_hourly[meter_id][row_energy_value[0]] = row_energy_value[1] |
|
326 | except Exception as e: |
|
327 | error_string = "Error in step 6.1 of shopfloor_energy_input_category.worker " + str(e) |
|
328 | if cursor_energy_db: |
|
329 | cursor_energy_db.close() |
|
330 | if cnx_energy_db: |
|
331 | cnx_energy_db.close() |
|
332 | print(error_string) |
|
333 | return error_string |
|
334 | ||
335 | #################################################################################################################### |
|
336 | # Step 7: for each virtual meter in list, get energy input data from energy database |
|
337 | #################################################################################################################### |
|
338 | energy_virtual_meter_hourly = dict() |
|
339 | if virtual_meter_list is not None and len(virtual_meter_list) > 0: |
|
340 | try: |
|
341 | for virtual_meter in virtual_meter_list: |
|
342 | virtual_meter_id = str(virtual_meter['id']) |
|
343 | ||
344 | query = (" SELECT start_datetime_utc, actual_value " |
|
345 | " FROM tbl_virtual_meter_hourly " |
|
346 | " WHERE virtual_meter_id = %s " |
|
347 | " AND start_datetime_utc >= %s " |
|
348 | " AND start_datetime_utc < %s " |
|
349 | " ORDER BY start_datetime_utc ") |
|
350 | cursor_energy_db.execute(query, (virtual_meter_id, start_datetime_utc, end_datetime_utc,)) |
|
351 | rows_energy_values = cursor_energy_db.fetchall() |
|
352 | if rows_energy_values is None or len(rows_energy_values) == 0: |
|
353 | energy_virtual_meter_hourly[virtual_meter_id] = None |
|
354 | else: |
|
355 | energy_virtual_meter_hourly[virtual_meter_id] = dict() |
|
356 | for row_energy_value in rows_energy_values: |
|
357 | energy_virtual_meter_hourly[virtual_meter_id][row_energy_value[0]] = row_energy_value[1] |
|
358 | except Exception as e: |
|
359 | error_string = "Error in step 7.1 of shopfloor_energy_input_category.worker " + str(e) |
|
360 | if cursor_energy_db: |
|
361 | cursor_energy_db.close() |
|
362 | if cnx_energy_db: |
|
363 | cnx_energy_db.close() |
|
364 | print(error_string) |
|
365 | return error_string |
|
366 | ||
367 | #################################################################################################################### |
|
368 | # Step 8: for each offline meter in list, get energy input data from energy database |
|
369 | #################################################################################################################### |
|
370 | energy_offline_meter_hourly = dict() |
|
371 | if offline_meter_list is not None and len(offline_meter_list) > 0: |
|
372 | try: |
|
373 | for offline_meter in offline_meter_list: |
|
374 | offline_meter_id = str(offline_meter['id']) |
|
375 | ||
376 | query = (" SELECT start_datetime_utc, actual_value " |
|
377 | " FROM tbl_offline_meter_hourly " |
|
378 | " WHERE offline_meter_id = %s " |
|
379 | " AND start_datetime_utc >= %s " |
|
380 | " AND start_datetime_utc < %s " |
|
381 | " ORDER BY start_datetime_utc ") |
|
382 | cursor_energy_db.execute(query, (offline_meter_id, start_datetime_utc, end_datetime_utc,)) |
|
383 | rows_energy_values = cursor_energy_db.fetchall() |
|
384 | if rows_energy_values is None or len(rows_energy_values) == 0: |
|
385 | energy_offline_meter_hourly[offline_meter_id] = None |
|
386 | else: |
|
387 | energy_offline_meter_hourly[offline_meter_id] = dict() |
|
388 | for row_energy_value in rows_energy_values: |
|
389 | energy_offline_meter_hourly[offline_meter_id][row_energy_value[0]] = row_energy_value[1] |
|
390 | ||
391 | except Exception as e: |
|
392 | error_string = "Error in step 8.1 of shopfloor_energy_input_category.worker " + str(e) |
|
393 | if cursor_energy_db: |
|
394 | cursor_energy_db.close() |
|
395 | if cnx_energy_db: |
|
396 | cnx_energy_db.close() |
|
397 | print(error_string) |
|
398 | return error_string |
|
399 | ||
400 | #################################################################################################################### |
|
401 | # Step 9: for each equipment in list, get energy input data from energy database |
|
402 | #################################################################################################################### |
|
403 | energy_equipment_hourly = dict() |
|
404 | if equipment_list is not None and len(equipment_list) > 0: |
|
405 | try: |
|
406 | for equipment in equipment_list: |
|
407 | equipment_id = str(equipment['id']) |
|
408 | query = (" SELECT start_datetime_utc, energy_category_id, actual_value " |
|
409 | " FROM tbl_equipment_input_category_hourly " |
|
410 | " WHERE equipment_id = %s " |
|
411 | " AND start_datetime_utc >= %s " |
|
412 | " AND start_datetime_utc < %s " |
|
413 | " ORDER BY start_datetime_utc ") |
|
414 | cursor_energy_db.execute(query, (equipment_id, start_datetime_utc, end_datetime_utc,)) |
|
415 | rows_energy_values = cursor_energy_db.fetchall() |
|
416 | if rows_energy_values is None or len(rows_energy_values) == 0: |
|
417 | energy_equipment_hourly[equipment_id] = None |
|
418 | else: |
|
419 | energy_equipment_hourly[equipment_id] = dict() |
|
420 | for row_value in rows_energy_values: |
|
421 | current_datetime_utc = row_value[0] |
|
422 | if current_datetime_utc not in energy_equipment_hourly[equipment_id]: |
|
423 | energy_equipment_hourly[equipment_id][current_datetime_utc] = dict() |
|
424 | energy_category_id = row_value[1] |
|
425 | actual_value = row_value[2] |
|
426 | energy_equipment_hourly[equipment_id][current_datetime_utc][energy_category_id] = \ |
|
427 | actual_value |
|
428 | except Exception as e: |
|
429 | error_string = "Error in step 9 of shopfloor_energy_input_category.worker " + str(e) |
|
430 | if cursor_energy_db: |
|
431 | cursor_energy_db.close() |
|
432 | if cnx_energy_db: |
|
433 | cnx_energy_db.close() |
|
434 | print(error_string) |
|
435 | return error_string |
|
436 | ||
437 | #################################################################################################################### |
|
438 | # Step 10: determine common time slot to aggregate |
|
439 | #################################################################################################################### |
|
440 | ||
441 | common_start_datetime_utc = start_datetime_utc |
|
442 | common_end_datetime_utc = end_datetime_utc |
|
443 | ||
444 | print("Getting common time slot of energy values for all meters") |
|
445 | if energy_meter_hourly is not None and len(energy_meter_hourly) > 0: |
|
446 | for meter_id, energy_hourly in energy_meter_hourly.items(): |
|
447 | if energy_hourly is None or len(energy_hourly) == 0: |
|
448 | common_start_datetime_utc = None |
|
449 | common_end_datetime_utc = None |
|
450 | break |
|
451 | else: |
|
452 | if common_start_datetime_utc < min(energy_hourly.keys()): |
|
453 | common_start_datetime_utc = min(energy_hourly.keys()) |
|
454 | if common_end_datetime_utc > max(energy_hourly.keys()): |
|
455 | common_end_datetime_utc = max(energy_hourly.keys()) |
|
456 | ||
457 | print("Getting common time slot of energy values for all virtual meters") |
|
458 | if common_start_datetime_utc is not None and common_start_datetime_utc is not None: |
|
459 | if energy_virtual_meter_hourly is not None and len(energy_virtual_meter_hourly) > 0: |
|
460 | for meter_id, energy_hourly in energy_virtual_meter_hourly.items(): |
|
461 | if energy_hourly is None or len(energy_hourly) == 0: |
|
462 | common_start_datetime_utc = None |
|
463 | common_end_datetime_utc = None |
|
464 | break |
|
465 | else: |
|
466 | if common_start_datetime_utc < min(energy_hourly.keys()): |
|
467 | common_start_datetime_utc = min(energy_hourly.keys()) |
|
468 | if common_end_datetime_utc > max(energy_hourly.keys()): |
|
469 | common_end_datetime_utc = max(energy_hourly.keys()) |
|
470 | ||
471 | print("Getting common time slot of energy values for all offline meters") |
|
472 | if common_start_datetime_utc is not None and common_start_datetime_utc is not None: |
|
473 | if energy_offline_meter_hourly is not None and len(energy_offline_meter_hourly) > 0: |
|
474 | for meter_id, energy_hourly in energy_offline_meter_hourly.items(): |
|
475 | if energy_hourly is None or len(energy_hourly) == 0: |
|
476 | common_start_datetime_utc = None |
|
477 | common_end_datetime_utc = None |
|
478 | break |
|
479 | else: |
|
480 | if common_start_datetime_utc < min(energy_hourly.keys()): |
|
481 | common_start_datetime_utc = min(energy_hourly.keys()) |
|
482 | if common_end_datetime_utc > max(energy_hourly.keys()): |
|
483 | common_end_datetime_utc = max(energy_hourly.keys()) |
|
484 | ||
485 | print("Getting common time slot of energy values for all equipments...") |
|
486 | if common_start_datetime_utc is not None and common_start_datetime_utc is not None: |
|
487 | if energy_equipment_hourly is not None and len(energy_equipment_hourly) > 0: |
|
488 | for equipment_id, energy_hourly in energy_equipment_hourly.items(): |
|
489 | if energy_hourly is None or len(energy_hourly) == 0: |
|
490 | common_start_datetime_utc = None |
|
491 | common_end_datetime_utc = None |
|
492 | break |
|
493 | else: |
|
494 | if common_start_datetime_utc < min(energy_hourly.keys()): |
|
495 | common_start_datetime_utc = min(energy_hourly.keys()) |
|
496 | if common_end_datetime_utc > max(energy_hourly.keys()): |
|
497 | common_end_datetime_utc = max(energy_hourly.keys()) |
|
498 | ||
499 | if (energy_meter_hourly is None or len(energy_meter_hourly) == 0) and \ |
|
500 | (energy_virtual_meter_hourly is None or len(energy_virtual_meter_hourly) == 0) and \ |
|
501 | (energy_offline_meter_hourly is None or len(energy_offline_meter_hourly) == 0) and \ |
|
502 | (energy_equipment_hourly is None or len(energy_equipment_hourly) == 0): |
|
503 | # There isn't any energy data |
|
504 | print("There isn't any energy data") |
|
505 | # continue the for shopfloor loop to the next shopfloor |
|
506 | print("continue the for shopfloor loop to the next shopfloor") |
|
507 | if cursor_energy_db: |
|
508 | cursor_energy_db.close() |
|
509 | if cnx_energy_db: |
|
510 | cnx_energy_db.close() |
|
511 | return None |
|
512 | ||
513 | print("common_start_datetime_utc: " + str(common_start_datetime_utc)) |
|
514 | print("common_end_datetime_utc: " + str(common_end_datetime_utc)) |
|
515 | ||
516 | #################################################################################################################### |
|
517 | # Step 11: aggregate energy data in the common time slot by energy categories and hourly |
|
518 | #################################################################################################################### |
|
519 | ||
520 | print("Step 11: aggregate energy data in the common time slot by energy categories and hourly") |
|
521 | aggregated_values = list() |
|
522 | try: |
|
523 | current_datetime_utc = common_start_datetime_utc |
|
524 | while common_start_datetime_utc is not None \ |
|
525 | and common_end_datetime_utc is not None \ |
|
526 | and current_datetime_utc <= common_end_datetime_utc: |
|
527 | aggregated_value = dict() |
|
528 | aggregated_value['start_datetime_utc'] = current_datetime_utc |
|
529 | aggregated_value['meta_data'] = dict() |
|
530 | ||
531 | if meter_list is not None and len(meter_list) > 0: |
|
532 | for meter in meter_list: |
|
533 | meter_id = str(meter['id']) |
|
534 | energy_category_id = meter['energy_category_id'] |
|
535 | actual_value = energy_meter_hourly[meter_id].get(current_datetime_utc, Decimal(0.0)) |
|
536 | aggregated_value['meta_data'][energy_category_id] = \ |
|
537 | aggregated_value['meta_data'].get(energy_category_id, Decimal(0.0)) + actual_value |
|
538 | ||
539 | if virtual_meter_list is not None and len(virtual_meter_list) > 0: |
|
540 | for virtual_meter in virtual_meter_list: |
|
541 | virtual_meter_id = str(virtual_meter['id']) |
|
542 | energy_category_id = virtual_meter['energy_category_id'] |
|
543 | actual_value = energy_virtual_meter_hourly[virtual_meter_id].get(current_datetime_utc, Decimal(0.0)) |
|
544 | aggregated_value['meta_data'][energy_category_id] = \ |
|
545 | aggregated_value['meta_data'].get(energy_category_id, Decimal(0.0)) + actual_value |
|
546 | ||
547 | if offline_meter_list is not None and len(offline_meter_list) > 0: |
|
548 | for offline_meter in offline_meter_list: |
|
549 | offline_meter_id = str(offline_meter['id']) |
|
550 | energy_category_id = offline_meter['energy_category_id'] |
|
551 | actual_value = energy_offline_meter_hourly[offline_meter_id].get(current_datetime_utc, Decimal(0.0)) |
|
552 | aggregated_value['meta_data'][energy_category_id] = \ |
|
553 | aggregated_value['meta_data'].get(energy_category_id, Decimal(0.0)) + actual_value |
|
554 | ||
555 | if equipment_list is not None and len(equipment_list) > 0: |
|
556 | for equipment in equipment_list: |
|
557 | equipment_id = str(equipment['id']) |
|
558 | meta_data_dict = energy_equipment_hourly[equipment_id].get(current_datetime_utc, None) |
|
559 | if meta_data_dict is not None and len(meta_data_dict) > 0: |
|
560 | for energy_category_id, actual_value in meta_data_dict.items(): |
|
561 | aggregated_value['meta_data'][energy_category_id] = \ |
|
562 | aggregated_value['meta_data'].get(energy_category_id, Decimal(0.0)) + actual_value |
|
563 | ||
564 | aggregated_values.append(aggregated_value) |
|
565 | ||
566 | current_datetime_utc += timedelta(minutes=config.minutes_to_count) |
|
567 | ||
568 | except Exception as e: |
|
569 | error_string = "Error in step 11 of shopfloor_energy_input_category.worker " + str(e) |
|
570 | if cursor_energy_db: |
|
571 | cursor_energy_db.close() |
|
572 | if cnx_energy_db: |
|
573 | cnx_energy_db.close() |
|
574 | print(error_string) |
|
575 | return error_string |
|
576 | ||
577 | #################################################################################################################### |
|
578 | # Step 12: save energy data to energy database |
|
579 | #################################################################################################################### |
|
580 | print("Step 12: save energy data to energy database") |
|
581 | ||
582 | if len(aggregated_values) > 0: |
|
583 | try: |
|
584 | add_values = (" INSERT INTO tbl_shopfloor_input_category_hourly " |
|
585 | " (shopfloor_id, " |
|
586 | " energy_category_id, " |
|
587 | " start_datetime_utc, " |
|
588 | " actual_value) " |
|
589 | " VALUES ") |
|
590 | ||
591 | for aggregated_value in aggregated_values: |
|
592 | for energy_category_id, actual_value in aggregated_value['meta_data'].items(): |
|
593 | add_values += " (" + str(shopfloor['id']) + "," |
|
594 | add_values += " " + str(energy_category_id) + "," |
|
595 | add_values += "'" + aggregated_value['start_datetime_utc'].isoformat()[0:19] + "'," |
|
596 | add_values += str(actual_value) + "), " |
|
597 | print("add_values:" + add_values) |
|
598 | # trim ", " at the end of string and then execute |
|
599 | cursor_energy_db.execute(add_values[:-2]) |
|
600 | cnx_energy_db.commit() |
|
601 | ||
602 | except Exception as e: |
|
603 | error_string = "Error in step 12.1 of shopfloor_energy_input_category.worker " + str(e) |
|
604 | print(error_string) |
|
605 | return error_string |
|
606 | finally: |
|
607 | if cursor_energy_db: |
|
608 | cursor_energy_db.close() |
|
609 | if cnx_energy_db: |
|
610 | cnx_energy_db.close() |
|
611 | else: |
|
612 | if cursor_energy_db: |
|
613 | cursor_energy_db.close() |
|
614 | if cnx_energy_db: |
|
615 | cnx_energy_db.close() |
|
616 |