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