1 | import random |
||
2 | import time |
||
3 | from datetime import datetime, timedelta |
||
4 | from decimal import Decimal |
||
5 | from multiprocessing import Pool |
||
6 | import mysql.connector |
||
7 | from sympy import sympify |
||
8 | import config |
||
9 | |||
10 | |||
11 | ######################################################################################################################## |
||
12 | # PROCEDURES: |
||
13 | # Step 1: Query all virtual meters |
||
14 | # Step 2: Create multiprocessing pool to call worker in parallel |
||
15 | ######################################################################################################################## |
||
16 | |||
17 | View Code Duplication | def calculate_hourly(logger): |
|
0 ignored issues
–
show
Duplication
introduced
by
![]() |
|||
18 | |||
19 | while True: |
||
20 | # the outermost while loop to reconnect server if there is a connection error |
||
21 | cnx_system_db = None |
||
22 | cursor_system_db = None |
||
23 | try: |
||
24 | cnx_system_db = mysql.connector.connect(**config.myems_system_db) |
||
25 | cursor_system_db = cnx_system_db.cursor() |
||
26 | except Exception as e: |
||
27 | logger.error("Error in step 0 of virtual_meter.calculate_hourly " + str(e)) |
||
28 | if cursor_system_db: |
||
29 | cursor_system_db.close() |
||
30 | if cnx_system_db: |
||
31 | cnx_system_db.close() |
||
32 | # sleep and continue the outer loop to reconnect the database |
||
33 | time.sleep(60) |
||
34 | continue |
||
35 | |||
36 | print("Connected to MyEMS System Database") |
||
37 | |||
38 | virtual_meter_list = list() |
||
39 | try: |
||
40 | cursor_system_db.execute(" SELECT id, name, equation " |
||
41 | " FROM tbl_virtual_meters " |
||
42 | " ORDER BY id ") |
||
43 | rows_virtual_meters = cursor_system_db.fetchall() |
||
44 | |||
45 | if rows_virtual_meters is None or len(rows_virtual_meters) == 0: |
||
46 | # sleep several minutes and continue the outer loop to reconnect the database |
||
47 | time.sleep(60) |
||
48 | continue |
||
49 | |||
50 | for row in rows_virtual_meters: |
||
51 | meta_result = {"id": row[0], "name": row[1], "equation": row[2]} |
||
52 | virtual_meter_list.append(meta_result) |
||
53 | |||
54 | except Exception as e: |
||
55 | logger.error("Error in step 1 of virtual meter calculate hourly " + str(e)) |
||
56 | # sleep and continue the outer loop to reconnect the database |
||
57 | time.sleep(60) |
||
58 | continue |
||
59 | finally: |
||
60 | if cursor_system_db: |
||
61 | cursor_system_db.close() |
||
62 | if cnx_system_db: |
||
63 | cnx_system_db.close() |
||
64 | |||
65 | # shuffle the virtual meter list for randomly calculating the meter hourly value |
||
66 | random.shuffle(virtual_meter_list) |
||
67 | |||
68 | print("Got all virtual meters in MyEMS System Database") |
||
69 | ################################################################################################################ |
||
70 | # Step 2: Create multiprocessing pool to call worker in parallel |
||
71 | ################################################################################################################ |
||
72 | p = Pool(processes=config.pool_size) |
||
73 | error_list = p.map(worker, virtual_meter_list) |
||
74 | p.close() |
||
75 | p.join() |
||
76 | |||
77 | for error in error_list: |
||
78 | if error is not None and len(error) > 0: |
||
79 | logger.error(error) |
||
80 | |||
81 | print("go to sleep ...") |
||
82 | time.sleep(60) |
||
83 | print("wake from sleep, and continue to work...") |
||
84 | |||
85 | |||
86 | ######################################################################################################################## |
||
87 | # Step 1: get start datetime and end datetime |
||
88 | # Step 2: parse the expression and get all meters, virtual meters, offline meters associated with the expression |
||
89 | # Step 3: query energy consumption values from table meter hourly, virtual meter hourly and offline meter hourly |
||
90 | # Step 4: evaluate the equation with variables values from previous step and save to table virtual meter hourly |
||
91 | # returns the error string for logging or returns None |
||
92 | ######################################################################################################################## |
||
93 | |||
94 | def worker(virtual_meter): |
||
95 | cnx_energy_db = None |
||
96 | cursor_energy_db = None |
||
97 | |||
98 | try: |
||
99 | cnx_energy_db = mysql.connector.connect(**config.myems_energy_db) |
||
100 | cursor_energy_db = cnx_energy_db.cursor() |
||
101 | except Exception as e: |
||
102 | if cursor_energy_db: |
||
103 | cursor_energy_db.close() |
||
104 | if cnx_energy_db: |
||
105 | cnx_energy_db.close() |
||
106 | return "Error in step 1.1 of virtual meter worker " + str(e) + " for '" + virtual_meter['name'] + "'" |
||
107 | |||
108 | print("Start to process virtual meter: " + "'" + virtual_meter['name']+"'") |
||
109 | |||
110 | #################################################################################################################### |
||
111 | # step 1: get start datetime and end datetime |
||
112 | # get latest timestamp from energy database in tbl_virtual_meter_hourly |
||
113 | #################################################################################################################### |
||
114 | |||
115 | try: |
||
116 | query = (" SELECT MAX(start_datetime_utc) " |
||
117 | " FROM tbl_virtual_meter_hourly " |
||
118 | " WHERE virtual_meter_id = %s ") |
||
119 | cursor_energy_db.execute(query, (virtual_meter['id'],)) |
||
120 | row_datetime = cursor_energy_db.fetchone() |
||
121 | except Exception as e: |
||
122 | if cursor_energy_db: |
||
123 | cursor_energy_db.close() |
||
124 | if cnx_energy_db: |
||
125 | cnx_energy_db.close() |
||
126 | return "Error in step 1.2 of virtual meter worker " + str(e) + " for '" + virtual_meter['name'] + "'" |
||
127 | |||
128 | start_datetime_utc = datetime.strptime(config.start_datetime_utc, '%Y-%m-%d %H:%M:%S') |
||
129 | start_datetime_utc = start_datetime_utc.replace(minute=0, second=0, microsecond=0, tzinfo=None) |
||
130 | |||
131 | if row_datetime is not None and len(row_datetime) > 0 and isinstance(row_datetime[0], datetime): |
||
132 | # replace second and microsecond with 0 |
||
133 | # note: do not replace minute in case of calculating in half hourly |
||
134 | start_datetime_utc = row_datetime[0].replace(second=0, microsecond=0, tzinfo=None) |
||
135 | # start from the next time slot |
||
136 | start_datetime_utc += timedelta(minutes=config.minutes_to_count) |
||
137 | |||
138 | end_datetime_utc = datetime.utcnow().replace() |
||
139 | end_datetime_utc = end_datetime_utc.replace(second=0, microsecond=0, tzinfo=None) |
||
140 | |||
141 | time_difference = end_datetime_utc - start_datetime_utc |
||
142 | time_difference_in_minutes = time_difference / timedelta(minutes=1) |
||
143 | if time_difference_in_minutes < config.minutes_to_count: |
||
144 | if cursor_energy_db: |
||
145 | cursor_energy_db.close() |
||
146 | if cnx_energy_db: |
||
147 | cnx_energy_db.close() |
||
148 | return "it isn't time to calculate" + " for '" + virtual_meter['name'] + "'" |
||
149 | elif time_difference_in_minutes > 60 * 24 * 30: |
||
150 | # avoid to caculate records more than one month |
||
151 | end_datetime_utc = start_datetime_utc + timedelta(minutes=60 * 24 * 30) |
||
152 | |||
153 | # trim end_datetime_utc |
||
154 | trimmed_end_datetime_utc = start_datetime_utc + timedelta(minutes=config.minutes_to_count) |
||
155 | while trimmed_end_datetime_utc <= end_datetime_utc: |
||
156 | trimmed_end_datetime_utc += timedelta(minutes=config.minutes_to_count) |
||
157 | |||
158 | end_datetime_utc = trimmed_end_datetime_utc - timedelta(minutes=config.minutes_to_count) |
||
159 | |||
160 | if end_datetime_utc <= start_datetime_utc: |
||
161 | if cursor_energy_db: |
||
162 | cursor_energy_db.close() |
||
163 | if cnx_energy_db: |
||
164 | cnx_energy_db.close() |
||
165 | return "it isn't time to calculate" + " for '" + virtual_meter['name'] + "'" |
||
166 | |||
167 | print("start_datetime_utc: " + start_datetime_utc.isoformat()[0:19] |
||
168 | + "end_datetime_utc: " + end_datetime_utc.isoformat()[0:19]) |
||
169 | |||
170 | ############################################################################################################ |
||
171 | # Step 2: parse the expression and get all meters, virtual meters, and |
||
172 | # offline meters associated with the expression |
||
173 | ############################################################################################################ |
||
174 | cnx_system_db = None |
||
175 | cursor_system_db = None |
||
176 | try: |
||
177 | cnx_system_db = mysql.connector.connect(**config.myems_system_db) |
||
178 | cursor_system_db = cnx_system_db.cursor() |
||
179 | except Exception as e: |
||
180 | if cursor_system_db: |
||
181 | cursor_system_db.close() |
||
182 | if cnx_system_db: |
||
183 | cnx_system_db.close() |
||
184 | if cursor_energy_db: |
||
185 | cursor_energy_db.close() |
||
186 | if cnx_energy_db: |
||
187 | cnx_energy_db.close() |
||
188 | return "Error in step 2.1 of virtual meter worker " + str(e) + " for '" + virtual_meter['name'] + "'" |
||
189 | |||
190 | meter_list_in_expression = list() |
||
191 | virtual_meter_list_in_expression = list() |
||
192 | offline_meter_list_in_expression = list() |
||
193 | try: |
||
194 | ######################################################################################################## |
||
195 | # get all meters associated with the expression |
||
196 | ######################################################################################################## |
||
197 | |||
198 | cursor_system_db.execute(" SELECT m.id as meter_id, v.name as variable_name " |
||
199 | " FROM tbl_meters m, tbl_variables v " |
||
200 | " WHERE m.id = v.meter_id " |
||
201 | " AND v.meter_type = 'meter' " |
||
202 | " AND v.virtual_meter_id = %s ", |
||
203 | (virtual_meter['id'], )) |
||
204 | rows = cursor_system_db.fetchall() |
||
205 | if rows is not None and len(rows) > 0: |
||
206 | for row in rows: |
||
207 | meter_list_in_expression.append({"meter_id": row[0], "variable_name": row[1].lower()}) |
||
208 | |||
209 | ######################################################################################################## |
||
210 | # get all virtual meters associated with the expression |
||
211 | ######################################################################################################## |
||
212 | |||
213 | cursor_system_db.execute(" SELECT m.id as virtual_meter_id, v.name as variable_name " |
||
214 | " FROM tbl_virtual_meters m, tbl_variables v " |
||
215 | " WHERE m.id = v.meter_id " |
||
216 | " AND v.meter_type = 'virtual_meter' " |
||
217 | " AND v.virtual_meter_id = %s ", |
||
218 | (virtual_meter['id'],)) |
||
219 | rows = cursor_system_db.fetchall() |
||
220 | if rows is not None and len(rows) > 0: |
||
221 | for row in rows: |
||
222 | virtual_meter_list_in_expression.append({"virtual_meter_id": row[0], |
||
223 | "variable_name": row[1].lower()}) |
||
224 | |||
225 | ######################################################################################################## |
||
226 | # get all offline meters associated with the expression |
||
227 | ######################################################################################################## |
||
228 | |||
229 | cursor_system_db.execute(" SELECT m.id as offline_meter_id, v.name as variable_name " |
||
230 | " FROM tbl_offline_meters m, tbl_variables v " |
||
231 | " WHERE m.id = v.meter_id " |
||
232 | " AND v.meter_type = 'offline_meter' " |
||
233 | " AND v.virtual_meter_id = %s ", |
||
234 | (virtual_meter['id'],)) |
||
235 | rows = cursor_system_db.fetchall() |
||
236 | if rows is not None and len(rows) > 0: |
||
237 | for row in rows: |
||
238 | offline_meter_list_in_expression.append({"offline_meter_id": row[0], |
||
239 | "variable_name": row[1].lower()}) |
||
240 | except Exception as e: |
||
241 | if cursor_energy_db: |
||
242 | cursor_energy_db.close() |
||
243 | if cnx_energy_db: |
||
244 | cnx_energy_db.close() |
||
245 | return "Error in step 2.2 of virtual meter worker " + str(e) + " for '" + virtual_meter['name'] + "'" |
||
246 | finally: |
||
247 | if cursor_system_db: |
||
248 | cursor_system_db.close() |
||
249 | if cnx_system_db: |
||
250 | cnx_system_db.close() |
||
251 | |||
252 | ############################################################################################################ |
||
253 | # Step 3: query energy consumption values from table meter hourly, virtual meter hourly |
||
254 | # and offline meter hourly |
||
255 | ############################################################################################################ |
||
256 | |||
257 | print("getting energy consumption values from myems_energy_db.tbl_meter_hourly...") |
||
258 | energy_meter_hourly = dict() |
||
259 | if meter_list_in_expression is not None and len(meter_list_in_expression) > 0: |
||
260 | try: |
||
261 | for meter_in_expression in meter_list_in_expression: |
||
262 | meter_id = str(meter_in_expression['meter_id']) |
||
263 | query = (" SELECT start_datetime_utc, actual_value " |
||
264 | " FROM tbl_meter_hourly " |
||
265 | " WHERE meter_id = %s AND start_datetime_utc >= %s AND start_datetime_utc < %s " |
||
266 | " ORDER BY start_datetime_utc ") |
||
267 | cursor_energy_db.execute(query, (meter_id, start_datetime_utc, end_datetime_utc, )) |
||
268 | rows_energy_values = cursor_energy_db.fetchall() |
||
269 | if rows_energy_values is None or len(rows_energy_values) == 0: |
||
270 | energy_meter_hourly[meter_id] = None |
||
271 | else: |
||
272 | energy_meter_hourly[meter_id] = dict() |
||
273 | for row_energy_value in rows_energy_values: |
||
274 | energy_meter_hourly[meter_id][row_energy_value[0]] = row_energy_value[1] |
||
275 | except Exception as e: |
||
276 | if cursor_energy_db: |
||
277 | cursor_energy_db.close() |
||
278 | if cnx_energy_db: |
||
279 | cnx_energy_db.close() |
||
280 | return "Error in step 3.2 virtual meter worker " + str(e) + " for '" + virtual_meter['name'] + "'" |
||
281 | |||
282 | print("getting energy consumption values from myems_energy_db.tbl_virtual_meter_hourly...") |
||
283 | energy_virtual_meter_hourly = dict() |
||
284 | if virtual_meter_list_in_expression is not None and len(virtual_meter_list_in_expression) > 0: |
||
285 | try: |
||
286 | for virtual_meter_in_expression in virtual_meter_list_in_expression: |
||
287 | virtual_meter_id = str(virtual_meter_in_expression['virtual_meter_id']) |
||
288 | query = (" SELECT start_datetime_utc, actual_value " |
||
289 | " FROM tbl_virtual_meter_hourly " |
||
290 | " WHERE virtual_meter_id = %s " |
||
291 | " AND start_datetime_utc >= %s AND start_datetime_utc < %s " |
||
292 | " ORDER BY start_datetime_utc ") |
||
293 | cursor_energy_db.execute(query, (virtual_meter_id, start_datetime_utc, end_datetime_utc,)) |
||
294 | rows_energy_values = cursor_energy_db.fetchall() |
||
295 | if rows_energy_values is None or len(rows_energy_values) == 0: |
||
296 | energy_virtual_meter_hourly[virtual_meter_id] = None |
||
297 | else: |
||
298 | energy_virtual_meter_hourly[virtual_meter_id] = dict() |
||
299 | for row_energy_value in rows_energy_values: |
||
300 | energy_virtual_meter_hourly[virtual_meter_id][row_energy_value[0]] = row_energy_value[1] |
||
301 | except Exception as e: |
||
302 | if cursor_energy_db: |
||
303 | cursor_energy_db.close() |
||
304 | if cnx_energy_db: |
||
305 | cnx_energy_db.close() |
||
306 | return "Error in step 3.3 virtual meter worker " + str(e) + " for '" + virtual_meter['name'] + "'" |
||
307 | |||
308 | print("getting energy consumption values from myems_energy_db.tbl_offline_meter_hourly...") |
||
309 | energy_offline_meter_hourly = dict() |
||
310 | if offline_meter_list_in_expression is not None and len(offline_meter_list_in_expression) > 0: |
||
311 | try: |
||
312 | for offline_meter_in_expression in offline_meter_list_in_expression: |
||
313 | offline_meter_id = str(offline_meter_in_expression['offline_meter_id']) |
||
314 | query = (" SELECT start_datetime_utc, actual_value " |
||
315 | " FROM tbl_offline_meter_hourly " |
||
316 | " WHERE offline_meter_id = %s " |
||
317 | " AND start_datetime_utc >= %s AND start_datetime_utc < %s " |
||
318 | " ORDER BY start_datetime_utc ") |
||
319 | cursor_energy_db.execute(query, (offline_meter_id, start_datetime_utc, end_datetime_utc,)) |
||
320 | rows_energy_values = cursor_energy_db.fetchall() |
||
321 | if rows_energy_values is None or len(rows_energy_values) == 0: |
||
322 | energy_offline_meter_hourly[offline_meter_id] = None |
||
323 | else: |
||
324 | energy_offline_meter_hourly[offline_meter_id] = dict() |
||
325 | for row_energy_value in rows_energy_values: |
||
326 | energy_offline_meter_hourly[offline_meter_id][row_energy_value[0]] = row_energy_value[1] |
||
327 | except Exception as e: |
||
328 | if cursor_energy_db: |
||
329 | cursor_energy_db.close() |
||
330 | if cnx_energy_db: |
||
331 | cnx_energy_db.close() |
||
332 | return "Error in step 3.4 virtual meter worker " + str(e) + " for '" + virtual_meter['name'] + "'" |
||
333 | |||
334 | ############################################################################################################ |
||
335 | # Step 4: evaluate the equation with variables values from previous step |
||
336 | # and save to table virtual meter hourly |
||
337 | ############################################################################################################ |
||
338 | |||
339 | print("getting common time slot of energy values for all meters...") |
||
340 | common_start_datetime_utc = start_datetime_utc |
||
341 | common_end_datetime_utc = end_datetime_utc |
||
342 | if energy_meter_hourly is not None and len(energy_meter_hourly) > 0: |
||
343 | for meter_id, energy_hourly in energy_meter_hourly.items(): |
||
344 | if energy_hourly is None or len(energy_hourly) == 0: |
||
345 | common_start_datetime_utc = None |
||
346 | common_end_datetime_utc = None |
||
347 | break |
||
348 | else: |
||
349 | if common_start_datetime_utc < min(energy_hourly.keys()): |
||
350 | common_start_datetime_utc = min(energy_hourly.keys()) |
||
351 | if common_end_datetime_utc > max(energy_hourly.keys()): |
||
352 | common_end_datetime_utc = max(energy_hourly.keys()) |
||
353 | |||
354 | print("getting common time slot of energy values for all virtual meters...") |
||
355 | if common_start_datetime_utc is not None and common_end_datetime_utc is not None: |
||
356 | if energy_virtual_meter_hourly is not None and len(energy_virtual_meter_hourly) > 0: |
||
357 | for meter_id, energy_hourly in energy_virtual_meter_hourly.items(): |
||
358 | if energy_hourly is None or len(energy_hourly) == 0: |
||
359 | common_start_datetime_utc = None |
||
360 | common_end_datetime_utc = None |
||
361 | break |
||
362 | else: |
||
363 | if common_start_datetime_utc < min(energy_hourly.keys()): |
||
364 | common_start_datetime_utc = min(energy_hourly.keys()) |
||
365 | if common_end_datetime_utc > max(energy_hourly.keys()): |
||
366 | common_end_datetime_utc = max(energy_hourly.keys()) |
||
367 | |||
368 | print("getting common time slot of energy values for all offline meters...") |
||
369 | if common_start_datetime_utc is not None and common_end_datetime_utc is not None: |
||
370 | if energy_offline_meter_hourly is not None and len(energy_offline_meter_hourly) > 0: |
||
371 | for meter_id, energy_hourly in energy_offline_meter_hourly.items(): |
||
372 | if energy_hourly is None or len(energy_hourly) == 0: |
||
373 | common_start_datetime_utc = None |
||
374 | common_end_datetime_utc = None |
||
375 | break |
||
376 | else: |
||
377 | if common_start_datetime_utc < min(energy_hourly.keys()): |
||
378 | common_start_datetime_utc = min(energy_hourly.keys()) |
||
379 | if common_end_datetime_utc > max(energy_hourly.keys()): |
||
380 | common_end_datetime_utc = max(energy_hourly.keys()) |
||
381 | |||
382 | print("evaluating the equation with SymPy...") |
||
383 | normalized_values = list() |
||
384 | |||
385 | ############################################################################################################ |
||
386 | # Converting Strings to SymPy Expressions |
||
387 | # The sympify function(that’s sympify, not to be confused with simplify) can be used to |
||
388 | # convert strings into SymPy expressions. |
||
389 | ############################################################################################################ |
||
390 | try: |
||
391 | expr = sympify(virtual_meter['equation'].lower()) |
||
392 | print("the expression to be evaluated: " + str(expr)) |
||
393 | current_datetime_utc = common_start_datetime_utc |
||
394 | print("common_start_datetime_utc: " + str(common_start_datetime_utc)) |
||
395 | print("common_end_datetime_utc: " + str(common_end_datetime_utc)) |
||
396 | while common_start_datetime_utc is not None \ |
||
397 | and common_end_datetime_utc is not None \ |
||
398 | and current_datetime_utc <= common_end_datetime_utc: |
||
399 | meta_data = dict() |
||
400 | meta_data['start_datetime_utc'] = current_datetime_utc |
||
401 | |||
402 | #################################################################################################### |
||
403 | # create a dictionary of Symbol: point pairs |
||
404 | #################################################################################################### |
||
405 | |||
406 | subs = dict() |
||
407 | |||
408 | #################################################################################################### |
||
409 | # Evaluating the expression at current_datetime_utc |
||
410 | #################################################################################################### |
||
411 | |||
412 | if meter_list_in_expression is not None and len(meter_list_in_expression) > 0: |
||
413 | for meter_in_expression in meter_list_in_expression: |
||
414 | meter_id = str(meter_in_expression['meter_id']) |
||
415 | actual_value = energy_meter_hourly[meter_id].get(current_datetime_utc, Decimal(0.0)) |
||
416 | subs[meter_in_expression['variable_name']] = actual_value |
||
417 | |||
418 | if virtual_meter_list_in_expression is not None and len(virtual_meter_list_in_expression) > 0: |
||
419 | for virtual_meter_in_expression in virtual_meter_list_in_expression: |
||
420 | virtual_meter_id = str(virtual_meter_in_expression['virtual_meter_id']) |
||
421 | actual_value = energy_virtual_meter_hourly[virtual_meter_id].get(current_datetime_utc, Decimal(0.0)) |
||
422 | subs[virtual_meter_in_expression['variable_name']] = actual_value |
||
423 | |||
424 | if offline_meter_list_in_expression is not None and len(offline_meter_list_in_expression) > 0: |
||
425 | for offline_meter_in_expression in offline_meter_list_in_expression: |
||
426 | offline_meter_id = str(offline_meter_in_expression['offline_meter_id']) |
||
427 | actual_value = energy_offline_meter_hourly[offline_meter_id].get(current_datetime_utc, Decimal(0.0)) |
||
428 | subs[offline_meter_in_expression['variable_name']] = actual_value |
||
429 | |||
430 | #################################################################################################### |
||
431 | # To numerically evaluate an expression with a Symbol at a point, |
||
432 | # we might use subs followed by evalf, |
||
433 | # but it is more efficient and numerically stable to pass the substitution to evalf |
||
434 | # using the subs flag, which takes a dictionary of Symbol: point pairs. |
||
435 | #################################################################################################### |
||
436 | |||
437 | meta_data['actual_value'] = expr.evalf(subs=subs) |
||
438 | |||
439 | normalized_values.append(meta_data) |
||
440 | |||
441 | current_datetime_utc += timedelta(minutes=config.minutes_to_count) |
||
442 | |||
443 | except Exception as e: |
||
444 | if cursor_energy_db: |
||
445 | cursor_energy_db.close() |
||
446 | if cnx_energy_db: |
||
447 | cnx_energy_db.close() |
||
448 | return "Error in step 4.1 virtual meter worker " + str(e) + " for '" + virtual_meter['name'] + "'" |
||
449 | |||
450 | print("saving energy values to table energy virtual meter hourly...") |
||
451 | |||
452 | View Code Duplication | while len(normalized_values) > 0: |
|
0 ignored issues
–
show
|
|||
453 | insert_100 = normalized_values[:100] |
||
454 | normalized_values = normalized_values[100:] |
||
455 | try: |
||
456 | add_values = (" INSERT INTO tbl_virtual_meter_hourly " |
||
457 | " (virtual_meter_id, start_datetime_utc, actual_value) " |
||
458 | " VALUES ") |
||
459 | |||
460 | for meta_data in insert_100: |
||
461 | add_values += " (" + str(virtual_meter['id']) + "," |
||
462 | add_values += "'" + meta_data['start_datetime_utc'].isoformat()[0:19] + "'," |
||
463 | add_values += str(meta_data['actual_value']) + "), " |
||
464 | print("add_values:" + add_values) |
||
465 | # trim ", " at the end of string and then execute |
||
466 | cursor_energy_db.execute(add_values[:-2]) |
||
467 | cnx_energy_db.commit() |
||
468 | except Exception as e: |
||
469 | if cursor_energy_db: |
||
470 | cursor_energy_db.close() |
||
471 | if cnx_energy_db: |
||
472 | cnx_energy_db.close() |
||
473 | return "Error in step 4.2 virtual meter worker " + str(e) + " for '" + virtual_meter['name'] + "'" |
||
474 | |||
475 | if cursor_energy_db: |
||
476 | cursor_energy_db.close() |
||
477 | if cnx_energy_db: |
||
478 | cnx_energy_db.close() |
||
479 | |||
480 | return None |
||
481 |