| @@ 21-269 (lines=249) @@ | ||
| 18 | ######################################################################################################################## |
|
| 19 | ||
| 20 | ||
| 21 | def main(logger): |
|
| 22 | ||
| 23 | while True: |
|
| 24 | # the outermost while loop |
|
| 25 | ################################################################################################################ |
|
| 26 | # Step 1: get all combined equipments |
|
| 27 | ################################################################################################################ |
|
| 28 | cnx_system_db = None |
|
| 29 | cursor_system_db = None |
|
| 30 | try: |
|
| 31 | cnx_system_db = mysql.connector.connect(**config.myems_system_db) |
|
| 32 | cursor_system_db = cnx_system_db.cursor() |
|
| 33 | except Exception as e: |
|
| 34 | logger.error("Error in step 1.1 of combined_equipment_billing_input_category " + str(e)) |
|
| 35 | if cursor_system_db: |
|
| 36 | cursor_system_db.close() |
|
| 37 | if cnx_system_db: |
|
| 38 | cnx_system_db.close() |
|
| 39 | # sleep and continue the outermost while loop |
|
| 40 | time.sleep(60) |
|
| 41 | continue |
|
| 42 | ||
| 43 | print("Connected to MyEMS System Database") |
|
| 44 | ||
| 45 | try: |
|
| 46 | cursor_system_db.execute(" SELECT id, name, cost_center_id " |
|
| 47 | " FROM tbl_combined_equipments " |
|
| 48 | " ORDER BY id ") |
|
| 49 | rows_combined_equipments = cursor_system_db.fetchall() |
|
| 50 | ||
| 51 | if rows_combined_equipments is None or len(rows_combined_equipments) == 0: |
|
| 52 | print("Step 1.2: There isn't any combined equipments. ") |
|
| 53 | if cursor_system_db: |
|
| 54 | cursor_system_db.close() |
|
| 55 | if cnx_system_db: |
|
| 56 | cnx_system_db.close() |
|
| 57 | # sleep and continue the outermost while loop |
|
| 58 | time.sleep(60) |
|
| 59 | continue |
|
| 60 | ||
| 61 | combined_equipment_list = list() |
|
| 62 | for row in rows_combined_equipments: |
|
| 63 | combined_equipment_list.append({"id": row[0], "name": row[1], "cost_center_id": row[2]}) |
|
| 64 | ||
| 65 | except Exception as e: |
|
| 66 | logger.error("Error in step 1.2 of combined_equipment_billing_input_category " + str(e)) |
|
| 67 | if cursor_system_db: |
|
| 68 | cursor_system_db.close() |
|
| 69 | if cnx_system_db: |
|
| 70 | cnx_system_db.close() |
|
| 71 | # sleep and continue the outermost while loop |
|
| 72 | time.sleep(60) |
|
| 73 | continue |
|
| 74 | ||
| 75 | print("Step 1.2: Got all combined_equipments from MyEMS System Database") |
|
| 76 | ||
| 77 | cnx_energy_db = None |
|
| 78 | cursor_energy_db = None |
|
| 79 | try: |
|
| 80 | cnx_energy_db = mysql.connector.connect(**config.myems_energy_db) |
|
| 81 | cursor_energy_db = cnx_energy_db.cursor() |
|
| 82 | except Exception as e: |
|
| 83 | logger.error("Error in step 1.3 of combined_equipment_billing_input_category " + str(e)) |
|
| 84 | if cursor_energy_db: |
|
| 85 | cursor_energy_db.close() |
|
| 86 | if cnx_energy_db: |
|
| 87 | cnx_energy_db.close() |
|
| 88 | ||
| 89 | if cursor_system_db: |
|
| 90 | cursor_system_db.close() |
|
| 91 | if cnx_system_db: |
|
| 92 | cnx_system_db.close() |
|
| 93 | # sleep and continue the outermost while loop |
|
| 94 | time.sleep(60) |
|
| 95 | continue |
|
| 96 | ||
| 97 | print("Connected to MyEMS Energy Database") |
|
| 98 | ||
| 99 | cnx_billing_db = None |
|
| 100 | cursor_billing_db = None |
|
| 101 | try: |
|
| 102 | cnx_billing_db = mysql.connector.connect(**config.myems_billing_db) |
|
| 103 | cursor_billing_db = cnx_billing_db.cursor() |
|
| 104 | except Exception as e: |
|
| 105 | logger.error("Error in step 1.4 of combined_equipment_billing_input_category " + str(e)) |
|
| 106 | if cursor_billing_db: |
|
| 107 | cursor_billing_db.close() |
|
| 108 | if cnx_billing_db: |
|
| 109 | cnx_billing_db.close() |
|
| 110 | ||
| 111 | if cursor_energy_db: |
|
| 112 | cursor_energy_db.close() |
|
| 113 | if cnx_energy_db: |
|
| 114 | cnx_energy_db.close() |
|
| 115 | ||
| 116 | if cursor_system_db: |
|
| 117 | cursor_system_db.close() |
|
| 118 | if cnx_system_db: |
|
| 119 | cnx_system_db.close() |
|
| 120 | # sleep and continue the outermost while loop |
|
| 121 | time.sleep(60) |
|
| 122 | continue |
|
| 123 | ||
| 124 | print("Connected to MyEMS Billing Database") |
|
| 125 | ||
| 126 | for combined_equipment in combined_equipment_list: |
|
| 127 | ||
| 128 | ############################################################################################################ |
|
| 129 | # Step 2: get the latest start_datetime_utc |
|
| 130 | ############################################################################################################ |
|
| 131 | print("Step 2: get the latest start_datetime_utc from billing database for " + combined_equipment['name']) |
|
| 132 | try: |
|
| 133 | cursor_billing_db.execute(" SELECT MAX(start_datetime_utc) " |
|
| 134 | " FROM tbl_combined_equipment_input_category_hourly " |
|
| 135 | " WHERE combined_equipment_id = %s ", |
|
| 136 | (combined_equipment['id'], )) |
|
| 137 | row_datetime = cursor_billing_db.fetchone() |
|
| 138 | start_datetime_utc = datetime.strptime(config.start_datetime_utc, '%Y-%m-%d %H:%M:%S') |
|
| 139 | start_datetime_utc = start_datetime_utc.replace(minute=0, second=0, microsecond=0, tzinfo=None) |
|
| 140 | ||
| 141 | if row_datetime is not None and len(row_datetime) > 0 and isinstance(row_datetime[0], datetime): |
|
| 142 | # replace second and microsecond with 0 |
|
| 143 | # note: do not replace minute in case of calculating in half hourly |
|
| 144 | start_datetime_utc = row_datetime[0].replace(second=0, microsecond=0, tzinfo=None) |
|
| 145 | # start from the next time slot |
|
| 146 | start_datetime_utc += timedelta(minutes=config.minutes_to_count) |
|
| 147 | ||
| 148 | print("start_datetime_utc: " + start_datetime_utc.isoformat()[0:19]) |
|
| 149 | except Exception as e: |
|
| 150 | logger.error("Error in step 2 of combined_equipment_billing_input_category " + str(e)) |
|
| 151 | # break the for combined equipment loop |
|
| 152 | break |
|
| 153 | ||
| 154 | ############################################################################################################ |
|
| 155 | # Step 3: get all energy input data since the latest start_datetime_utc |
|
| 156 | ############################################################################################################ |
|
| 157 | print("Step 3: get all energy input data since the latest start_datetime_utc") |
|
| 158 | ||
| 159 | query = (" SELECT start_datetime_utc, energy_category_id, actual_value " |
|
| 160 | " FROM tbl_combined_equipment_input_category_hourly " |
|
| 161 | " WHERE combined_equipment_id = %s AND start_datetime_utc >= %s " |
|
| 162 | " ORDER BY id ") |
|
| 163 | cursor_energy_db.execute(query, (combined_equipment['id'], start_datetime_utc, )) |
|
| 164 | rows_hourly = cursor_energy_db.fetchall() |
|
| 165 | ||
| 166 | if rows_hourly is None or len(rows_hourly) == 0: |
|
| 167 | print("Step 3: There isn't any energy input data to calculate. ") |
|
| 168 | # continue the for combined equipment loop |
|
| 169 | continue |
|
| 170 | ||
| 171 | energy_dict = dict() |
|
| 172 | energy_category_list = list() |
|
| 173 | end_datetime_utc = start_datetime_utc |
|
| 174 | for row_hourly in rows_hourly: |
|
| 175 | current_datetime_utc = row_hourly[0] |
|
| 176 | energy_category_id = row_hourly[1] |
|
| 177 | ||
| 178 | if energy_category_id not in energy_category_list: |
|
| 179 | energy_category_list.append(energy_category_id) |
|
| 180 | ||
| 181 | actual_value = row_hourly[2] |
|
| 182 | if energy_dict.get(current_datetime_utc) is None: |
|
| 183 | energy_dict[current_datetime_utc] = dict() |
|
| 184 | energy_dict[current_datetime_utc][energy_category_id] = actual_value |
|
| 185 | if current_datetime_utc > end_datetime_utc: |
|
| 186 | end_datetime_utc = current_datetime_utc |
|
| 187 | ||
| 188 | ############################################################################################################ |
|
| 189 | # Step 4: get tariffs |
|
| 190 | ############################################################################################################ |
|
| 191 | print("Step 4: get tariffs") |
|
| 192 | tariff_dict = dict() |
|
| 193 | for energy_category_id in energy_category_list: |
|
| 194 | tariff_dict[energy_category_id] = \ |
|
| 195 | tariff.get_energy_category_tariffs(combined_equipment['cost_center_id'], |
|
| 196 | energy_category_id, |
|
| 197 | start_datetime_utc, |
|
| 198 | end_datetime_utc) |
|
| 199 | ############################################################################################################ |
|
| 200 | # Step 5: calculate billing by multiplying energy with tariff |
|
| 201 | ############################################################################################################ |
|
| 202 | print("Step 5: calculate billing by multiplying energy with tariff") |
|
| 203 | billing_dict = dict() |
|
| 204 | ||
| 205 | if len(energy_dict) > 0: |
|
| 206 | for current_datetime_utc in energy_dict.keys(): |
|
| 207 | billing_dict[current_datetime_utc] = dict() |
|
| 208 | for energy_category_id in energy_category_list: |
|
| 209 | current_tariff = tariff_dict[energy_category_id].get(current_datetime_utc) |
|
| 210 | current_energy = energy_dict[current_datetime_utc].get(energy_category_id) |
|
| 211 | if current_tariff is not None \ |
|
| 212 | and isinstance(current_tariff, Decimal) \ |
|
| 213 | and current_energy is not None \ |
|
| 214 | and isinstance(current_energy, Decimal): |
|
| 215 | billing_dict[current_datetime_utc][energy_category_id] = \ |
|
| 216 | current_energy * current_tariff |
|
| 217 | ||
| 218 | if len(billing_dict[current_datetime_utc]) == 0: |
|
| 219 | del billing_dict[current_datetime_utc] |
|
| 220 | ||
| 221 | ############################################################################################################ |
|
| 222 | # Step 6: save billing data to billing database |
|
| 223 | ############################################################################################################ |
|
| 224 | print("Step 6: save billing data to billing database") |
|
| 225 | ||
| 226 | if len(billing_dict) > 0: |
|
| 227 | try: |
|
| 228 | add_values = (" INSERT INTO tbl_combined_equipment_input_category_hourly " |
|
| 229 | " (combined_equipment_id, " |
|
| 230 | " energy_category_id, " |
|
| 231 | " start_datetime_utc, " |
|
| 232 | " actual_value) " |
|
| 233 | " VALUES ") |
|
| 234 | ||
| 235 | for current_datetime_utc in billing_dict: |
|
| 236 | for energy_category_id in energy_category_list: |
|
| 237 | current_billing = billing_dict[current_datetime_utc].get(energy_category_id) |
|
| 238 | if current_billing is not None and isinstance(current_billing, Decimal): |
|
| 239 | add_values += " (" + str(combined_equipment['id']) + "," |
|
| 240 | add_values += " " + str(energy_category_id) + "," |
|
| 241 | add_values += "'" + current_datetime_utc.isoformat()[0:19] + "'," |
|
| 242 | add_values += str(billing_dict[current_datetime_utc][energy_category_id]) + "), " |
|
| 243 | print("add_values:" + add_values) |
|
| 244 | # trim ", " at the end of string and then execute |
|
| 245 | cursor_billing_db.execute(add_values[:-2]) |
|
| 246 | cnx_billing_db.commit() |
|
| 247 | except Exception as e: |
|
| 248 | logger.error("Error in step 6 of combined_equipment_billing_input_category " + str(e)) |
|
| 249 | # break the for combined equipment loop |
|
| 250 | break |
|
| 251 | ||
| 252 | # end of for combined equipment loop |
|
| 253 | if cnx_system_db: |
|
| 254 | cnx_system_db.close() |
|
| 255 | if cursor_system_db: |
|
| 256 | cursor_system_db.close() |
|
| 257 | ||
| 258 | if cnx_energy_db: |
|
| 259 | cnx_energy_db.close() |
|
| 260 | if cursor_energy_db: |
|
| 261 | cursor_energy_db.close() |
|
| 262 | ||
| 263 | if cnx_billing_db: |
|
| 264 | cnx_billing_db.close() |
|
| 265 | if cursor_billing_db: |
|
| 266 | cursor_billing_db.close() |
|
| 267 | print("go to sleep 300 seconds...") |
|
| 268 | time.sleep(300) |
|
| 269 | print("wake from sleep, and continue to work...") |
|
| 270 | # end of the outermost while loop |
|
| 271 | ||
| @@ 21-269 (lines=249) @@ | ||
| 18 | ######################################################################################################################## |
|
| 19 | ||
| 20 | ||
| 21 | def main(logger): |
|
| 22 | ||
| 23 | while True: |
|
| 24 | # the outermost while loop |
|
| 25 | ################################################################################################################ |
|
| 26 | # Step 1: get all combined equipments |
|
| 27 | ################################################################################################################ |
|
| 28 | cnx_system_db = None |
|
| 29 | cursor_system_db = None |
|
| 30 | try: |
|
| 31 | cnx_system_db = mysql.connector.connect(**config.myems_system_db) |
|
| 32 | cursor_system_db = cnx_system_db.cursor() |
|
| 33 | except Exception as e: |
|
| 34 | logger.error("Error in step 1.1 of combined_equipment_billing_input_item " + str(e)) |
|
| 35 | if cursor_system_db: |
|
| 36 | cursor_system_db.close() |
|
| 37 | if cnx_system_db: |
|
| 38 | cnx_system_db.close() |
|
| 39 | # sleep and continue the outermost while loop |
|
| 40 | time.sleep(60) |
|
| 41 | continue |
|
| 42 | ||
| 43 | print("Connected to MyEMS System Database") |
|
| 44 | ||
| 45 | try: |
|
| 46 | cursor_system_db.execute(" SELECT id, name, cost_center_id " |
|
| 47 | " FROM tbl_combined_equipments " |
|
| 48 | " ORDER BY id ") |
|
| 49 | rows_combined_equipments = cursor_system_db.fetchall() |
|
| 50 | ||
| 51 | if rows_combined_equipments is None or len(rows_combined_equipments) == 0: |
|
| 52 | print("Step 1.2: There isn't any combined equipments. ") |
|
| 53 | if cursor_system_db: |
|
| 54 | cursor_system_db.close() |
|
| 55 | if cnx_system_db: |
|
| 56 | cnx_system_db.close() |
|
| 57 | # sleep and continue the outermost while loop |
|
| 58 | time.sleep(60) |
|
| 59 | continue |
|
| 60 | ||
| 61 | combined_equipment_list = list() |
|
| 62 | for row in rows_combined_equipments: |
|
| 63 | combined_equipment_list.append({"id": row[0], "name": row[1], "cost_center_id": row[2]}) |
|
| 64 | ||
| 65 | except Exception as e: |
|
| 66 | logger.error("Error in step 1.2 of combined_equipment_billing_input_item " + str(e)) |
|
| 67 | if cursor_system_db: |
|
| 68 | cursor_system_db.close() |
|
| 69 | if cnx_system_db: |
|
| 70 | cnx_system_db.close() |
|
| 71 | # sleep and continue the outermost while loop |
|
| 72 | time.sleep(60) |
|
| 73 | continue |
|
| 74 | ||
| 75 | print("Step 1.2: Got all combined equipments from MyEMS System Database") |
|
| 76 | ||
| 77 | cnx_energy_db = None |
|
| 78 | cursor_energy_db = None |
|
| 79 | try: |
|
| 80 | cnx_energy_db = mysql.connector.connect(**config.myems_energy_db) |
|
| 81 | cursor_energy_db = cnx_energy_db.cursor() |
|
| 82 | except Exception as e: |
|
| 83 | logger.error("Error in step 1.3 of combined_equipment_billing_input_item " + str(e)) |
|
| 84 | if cursor_energy_db: |
|
| 85 | cursor_energy_db.close() |
|
| 86 | if cnx_energy_db: |
|
| 87 | cnx_energy_db.close() |
|
| 88 | ||
| 89 | if cursor_system_db: |
|
| 90 | cursor_system_db.close() |
|
| 91 | if cnx_system_db: |
|
| 92 | cnx_system_db.close() |
|
| 93 | # sleep and continue the outermost while loop |
|
| 94 | time.sleep(60) |
|
| 95 | continue |
|
| 96 | ||
| 97 | print("Connected to MyEMS Energy Database") |
|
| 98 | ||
| 99 | cnx_billing_db = None |
|
| 100 | cursor_billing_db = None |
|
| 101 | try: |
|
| 102 | cnx_billing_db = mysql.connector.connect(**config.myems_billing_db) |
|
| 103 | cursor_billing_db = cnx_billing_db.cursor() |
|
| 104 | except Exception as e: |
|
| 105 | logger.error("Error in step 1.4 of combined_equipment_billing_input_item " + str(e)) |
|
| 106 | if cursor_billing_db: |
|
| 107 | cursor_billing_db.close() |
|
| 108 | if cnx_billing_db: |
|
| 109 | cnx_billing_db.close() |
|
| 110 | ||
| 111 | if cursor_energy_db: |
|
| 112 | cursor_energy_db.close() |
|
| 113 | if cnx_energy_db: |
|
| 114 | cnx_energy_db.close() |
|
| 115 | ||
| 116 | if cursor_system_db: |
|
| 117 | cursor_system_db.close() |
|
| 118 | if cnx_system_db: |
|
| 119 | cnx_system_db.close() |
|
| 120 | # sleep and continue the outermost while loop |
|
| 121 | time.sleep(60) |
|
| 122 | continue |
|
| 123 | ||
| 124 | print("Connected to MyEMS Billing Database") |
|
| 125 | ||
| 126 | for combined_equipment in combined_equipment_list: |
|
| 127 | ||
| 128 | ############################################################################################################ |
|
| 129 | # Step 2: get the latest start_datetime_utc |
|
| 130 | ############################################################################################################ |
|
| 131 | print("Step 2: get the latest start_datetime_utc from billing database for " + combined_equipment['name']) |
|
| 132 | try: |
|
| 133 | cursor_billing_db.execute(" SELECT MAX(start_datetime_utc) " |
|
| 134 | " FROM tbl_combined_equipment_input_item_hourly " |
|
| 135 | " WHERE combined_equipment_id = %s ", |
|
| 136 | (combined_equipment['id'], )) |
|
| 137 | row_datetime = cursor_billing_db.fetchone() |
|
| 138 | start_datetime_utc = datetime.strptime(config.start_datetime_utc, '%Y-%m-%d %H:%M:%S') |
|
| 139 | start_datetime_utc = start_datetime_utc.replace(minute=0, second=0, microsecond=0, tzinfo=None) |
|
| 140 | ||
| 141 | if row_datetime is not None and len(row_datetime) > 0 and isinstance(row_datetime[0], datetime): |
|
| 142 | # replace second and microsecond with 0 |
|
| 143 | # note: do not replace minute in case of calculating in half hourly |
|
| 144 | start_datetime_utc = row_datetime[0].replace(second=0, microsecond=0, tzinfo=None) |
|
| 145 | # start from the next time slot |
|
| 146 | start_datetime_utc += timedelta(minutes=config.minutes_to_count) |
|
| 147 | ||
| 148 | print("start_datetime_utc: " + start_datetime_utc.isoformat()[0:19]) |
|
| 149 | except Exception as e: |
|
| 150 | logger.error("Error in step 2 of combined_equipment_billing_input_item " + str(e)) |
|
| 151 | # break the for combined equipment loop |
|
| 152 | break |
|
| 153 | ||
| 154 | ############################################################################################################ |
|
| 155 | # Step 3: get all energy input data since the latest start_datetime_utc |
|
| 156 | ############################################################################################################ |
|
| 157 | print("Step 3: get all energy input data since the latest start_datetime_utc") |
|
| 158 | ||
| 159 | query = (" SELECT start_datetime_utc, energy_item_id, actual_value " |
|
| 160 | " FROM tbl_combined_equipment_input_item_hourly " |
|
| 161 | " WHERE combined_equipment_id = %s AND start_datetime_utc >= %s " |
|
| 162 | " ORDER BY id ") |
|
| 163 | cursor_energy_db.execute(query, (combined_equipment['id'], start_datetime_utc, )) |
|
| 164 | rows_hourly = cursor_energy_db.fetchall() |
|
| 165 | ||
| 166 | if rows_hourly is None or len(rows_hourly) == 0: |
|
| 167 | print("Step 3: There isn't any energy input data to calculate. ") |
|
| 168 | # continue the for combined equipment loop |
|
| 169 | continue |
|
| 170 | ||
| 171 | energy_dict = dict() |
|
| 172 | energy_item_list = list() |
|
| 173 | end_datetime_utc = start_datetime_utc |
|
| 174 | for row_hourly in rows_hourly: |
|
| 175 | current_datetime_utc = row_hourly[0] |
|
| 176 | energy_item_id = row_hourly[1] |
|
| 177 | ||
| 178 | if energy_item_id not in energy_item_list: |
|
| 179 | energy_item_list.append(energy_item_id) |
|
| 180 | ||
| 181 | actual_value = row_hourly[2] |
|
| 182 | if energy_dict.get(current_datetime_utc) is None: |
|
| 183 | energy_dict[current_datetime_utc] = dict() |
|
| 184 | energy_dict[current_datetime_utc][energy_item_id] = actual_value |
|
| 185 | if current_datetime_utc > end_datetime_utc: |
|
| 186 | end_datetime_utc = current_datetime_utc |
|
| 187 | ||
| 188 | ############################################################################################################ |
|
| 189 | # Step 4: get tariffs |
|
| 190 | ############################################################################################################ |
|
| 191 | print("Step 4: get tariffs") |
|
| 192 | tariff_dict = dict() |
|
| 193 | for energy_item_id in energy_item_list: |
|
| 194 | tariff_dict[energy_item_id] = \ |
|
| 195 | tariff.get_energy_item_tariffs(combined_equipment['cost_center_id'], |
|
| 196 | energy_item_id, |
|
| 197 | start_datetime_utc, |
|
| 198 | end_datetime_utc) |
|
| 199 | ############################################################################################################ |
|
| 200 | # Step 5: calculate billing by multiplying energy with tariff |
|
| 201 | ############################################################################################################ |
|
| 202 | print("Step 5: calculate billing by multiplying energy with tariff") |
|
| 203 | billing_dict = dict() |
|
| 204 | ||
| 205 | if len(energy_dict) > 0: |
|
| 206 | for current_datetime_utc in energy_dict.keys(): |
|
| 207 | billing_dict[current_datetime_utc] = dict() |
|
| 208 | for energy_item_id in energy_item_list: |
|
| 209 | current_tariff = tariff_dict[energy_item_id].get(current_datetime_utc) |
|
| 210 | current_energy = energy_dict[current_datetime_utc].get(energy_item_id) |
|
| 211 | if current_tariff is not None \ |
|
| 212 | and isinstance(current_tariff, Decimal) \ |
|
| 213 | and current_energy is not None \ |
|
| 214 | and isinstance(current_energy, Decimal): |
|
| 215 | billing_dict[current_datetime_utc][energy_item_id] = \ |
|
| 216 | current_energy * current_tariff |
|
| 217 | ||
| 218 | if len(billing_dict[current_datetime_utc]) == 0: |
|
| 219 | del billing_dict[current_datetime_utc] |
|
| 220 | ||
| 221 | ############################################################################################################ |
|
| 222 | # Step 6: save billing data to billing database |
|
| 223 | ############################################################################################################ |
|
| 224 | print("Step 6: save billing data to billing database") |
|
| 225 | ||
| 226 | if len(billing_dict) > 0: |
|
| 227 | try: |
|
| 228 | add_values = (" INSERT INTO tbl_combined_equipment_input_item_hourly " |
|
| 229 | " (combined_equipment_id, " |
|
| 230 | " energy_item_id, " |
|
| 231 | " start_datetime_utc, " |
|
| 232 | " actual_value) " |
|
| 233 | " VALUES ") |
|
| 234 | ||
| 235 | for current_datetime_utc in billing_dict: |
|
| 236 | for energy_item_id in energy_item_list: |
|
| 237 | current_billing = billing_dict[current_datetime_utc].get(energy_item_id) |
|
| 238 | if current_billing is not None and isinstance(current_billing, Decimal): |
|
| 239 | add_values += " (" + str(combined_equipment['id']) + "," |
|
| 240 | add_values += " " + str(energy_item_id) + "," |
|
| 241 | add_values += "'" + current_datetime_utc.isoformat()[0:19] + "'," |
|
| 242 | add_values += str(billing_dict[current_datetime_utc][energy_item_id]) + "), " |
|
| 243 | print("add_values:" + add_values) |
|
| 244 | # trim ", " at the end of string and then execute |
|
| 245 | cursor_billing_db.execute(add_values[:-2]) |
|
| 246 | cnx_billing_db.commit() |
|
| 247 | except Exception as e: |
|
| 248 | logger.error("Error in step 6 of combined_equipment_billing_input_item " + str(e)) |
|
| 249 | # break the for combined equipment loop |
|
| 250 | break |
|
| 251 | ||
| 252 | # end of for combined equipment loop |
|
| 253 | if cnx_system_db: |
|
| 254 | cnx_system_db.close() |
|
| 255 | if cursor_system_db: |
|
| 256 | cursor_system_db.close() |
|
| 257 | ||
| 258 | if cnx_energy_db: |
|
| 259 | cnx_energy_db.close() |
|
| 260 | if cursor_energy_db: |
|
| 261 | cursor_energy_db.close() |
|
| 262 | ||
| 263 | if cnx_billing_db: |
|
| 264 | cnx_billing_db.close() |
|
| 265 | if cursor_billing_db: |
|
| 266 | cursor_billing_db.close() |
|
| 267 | print("go to sleep 300 seconds...") |
|
| 268 | time.sleep(300) |
|
| 269 | print("wake from sleep, and continue to work...") |
|
| 270 | # end of the outermost while loop |
|
| 271 | ||
| @@ 21-269 (lines=249) @@ | ||
| 18 | ######################################################################################################################## |
|
| 19 | ||
| 20 | ||
| 21 | def main(logger): |
|
| 22 | ||
| 23 | while True: |
|
| 24 | # the outermost while loop |
|
| 25 | ################################################################################################################ |
|
| 26 | # Step 1: get all combined equipments |
|
| 27 | ################################################################################################################ |
|
| 28 | cnx_system_db = None |
|
| 29 | cursor_system_db = None |
|
| 30 | try: |
|
| 31 | cnx_system_db = mysql.connector.connect(**config.myems_system_db) |
|
| 32 | cursor_system_db = cnx_system_db.cursor() |
|
| 33 | except Exception as e: |
|
| 34 | logger.error("Error in step 1.1 of combined_equipment_billing_input_category " + str(e)) |
|
| 35 | if cursor_system_db: |
|
| 36 | cursor_system_db.close() |
|
| 37 | if cnx_system_db: |
|
| 38 | cnx_system_db.close() |
|
| 39 | # sleep and continue the outermost while loop |
|
| 40 | time.sleep(60) |
|
| 41 | continue |
|
| 42 | ||
| 43 | print("Connected to MyEMS System Database") |
|
| 44 | ||
| 45 | try: |
|
| 46 | cursor_system_db.execute(" SELECT id, name, cost_center_id " |
|
| 47 | " FROM tbl_combined_equipments " |
|
| 48 | " ORDER BY id ") |
|
| 49 | rows_combined_equipments = cursor_system_db.fetchall() |
|
| 50 | ||
| 51 | if rows_combined_equipments is None or len(rows_combined_equipments) == 0: |
|
| 52 | print("Step 1.2: There isn't any combined equipments. ") |
|
| 53 | if cursor_system_db: |
|
| 54 | cursor_system_db.close() |
|
| 55 | if cnx_system_db: |
|
| 56 | cnx_system_db.close() |
|
| 57 | # sleep and continue the outermost while loop |
|
| 58 | time.sleep(60) |
|
| 59 | continue |
|
| 60 | ||
| 61 | combined_equipment_list = list() |
|
| 62 | for row in rows_combined_equipments: |
|
| 63 | combined_equipment_list.append({"id": row[0], "name": row[1], "cost_center_id": row[2]}) |
|
| 64 | ||
| 65 | except Exception as e: |
|
| 66 | logger.error("Error in step 1.2 of combined_equipment_billing_output_category " + str(e)) |
|
| 67 | if cursor_system_db: |
|
| 68 | cursor_system_db.close() |
|
| 69 | if cnx_system_db: |
|
| 70 | cnx_system_db.close() |
|
| 71 | # sleep and continue the outermost while loop |
|
| 72 | time.sleep(60) |
|
| 73 | continue |
|
| 74 | ||
| 75 | print("Step 1.2: Got all combined equipments from MyEMS System Database") |
|
| 76 | ||
| 77 | cnx_energy_db = None |
|
| 78 | cursor_energy_db = None |
|
| 79 | try: |
|
| 80 | cnx_energy_db = mysql.connector.connect(**config.myems_energy_db) |
|
| 81 | cursor_energy_db = cnx_energy_db.cursor() |
|
| 82 | except Exception as e: |
|
| 83 | logger.error("Error in step 1.3 of combined_equipment_billing_output_category " + str(e)) |
|
| 84 | if cursor_energy_db: |
|
| 85 | cursor_energy_db.close() |
|
| 86 | if cnx_energy_db: |
|
| 87 | cnx_energy_db.close() |
|
| 88 | ||
| 89 | if cursor_system_db: |
|
| 90 | cursor_system_db.close() |
|
| 91 | if cnx_system_db: |
|
| 92 | cnx_system_db.close() |
|
| 93 | # sleep and continue the outermost while loop |
|
| 94 | time.sleep(60) |
|
| 95 | continue |
|
| 96 | ||
| 97 | print("Connected to MyEMS Energy Database") |
|
| 98 | ||
| 99 | cnx_billing_db = None |
|
| 100 | cursor_billing_db = None |
|
| 101 | try: |
|
| 102 | cnx_billing_db = mysql.connector.connect(**config.myems_billing_db) |
|
| 103 | cursor_billing_db = cnx_billing_db.cursor() |
|
| 104 | except Exception as e: |
|
| 105 | logger.error("Error in step 1.4 of combined_equipment_billing_output_category " + str(e)) |
|
| 106 | if cursor_billing_db: |
|
| 107 | cursor_billing_db.close() |
|
| 108 | if cnx_billing_db: |
|
| 109 | cnx_billing_db.close() |
|
| 110 | ||
| 111 | if cursor_energy_db: |
|
| 112 | cursor_energy_db.close() |
|
| 113 | if cnx_energy_db: |
|
| 114 | cnx_energy_db.close() |
|
| 115 | ||
| 116 | if cursor_system_db: |
|
| 117 | cursor_system_db.close() |
|
| 118 | if cnx_system_db: |
|
| 119 | cnx_system_db.close() |
|
| 120 | # sleep and continue the outermost while loop |
|
| 121 | time.sleep(60) |
|
| 122 | continue |
|
| 123 | ||
| 124 | print("Connected to MyEMS Billing Database") |
|
| 125 | ||
| 126 | for combined_equipment in combined_equipment_list: |
|
| 127 | ||
| 128 | ############################################################################################################ |
|
| 129 | # Step 2: get the latest start_datetime_utc |
|
| 130 | ############################################################################################################ |
|
| 131 | print("Step 2: get the latest start_datetime_utc from billing database for " + combined_equipment['name']) |
|
| 132 | try: |
|
| 133 | cursor_billing_db.execute(" SELECT MAX(start_datetime_utc) " |
|
| 134 | " FROM tbl_combined_equipment_output_category_hourly " |
|
| 135 | " WHERE combined_equipment_id = %s ", |
|
| 136 | (combined_equipment['id'], )) |
|
| 137 | row_datetime = cursor_billing_db.fetchone() |
|
| 138 | start_datetime_utc = datetime.strptime(config.start_datetime_utc, '%Y-%m-%d %H:%M:%S') |
|
| 139 | start_datetime_utc = start_datetime_utc.replace(minute=0, second=0, microsecond=0, tzinfo=None) |
|
| 140 | ||
| 141 | if row_datetime is not None and len(row_datetime) > 0 and isinstance(row_datetime[0], datetime): |
|
| 142 | # replace second and microsecond with 0 |
|
| 143 | # note: do not replace minute in case of calculating in half hourly |
|
| 144 | start_datetime_utc = row_datetime[0].replace(second=0, microsecond=0, tzinfo=None) |
|
| 145 | # start from the next time slot |
|
| 146 | start_datetime_utc += timedelta(minutes=config.minutes_to_count) |
|
| 147 | ||
| 148 | print("start_datetime_utc: " + start_datetime_utc.isoformat()[0:19]) |
|
| 149 | except Exception as e: |
|
| 150 | logger.error("Error in step 2 of combined_equipment_billing_output_category " + str(e)) |
|
| 151 | # break the for combined equipment loop |
|
| 152 | break |
|
| 153 | ||
| 154 | ############################################################################################################ |
|
| 155 | # Step 3: get all energy output data since the latest start_datetime_utc |
|
| 156 | ############################################################################################################ |
|
| 157 | print("Step 3: get all energy output data since the latest start_datetime_utc") |
|
| 158 | ||
| 159 | query = (" SELECT start_datetime_utc, energy_category_id, actual_value " |
|
| 160 | " FROM tbl_combined_equipment_output_category_hourly " |
|
| 161 | " WHERE combined_equipment_id = %s AND start_datetime_utc >= %s " |
|
| 162 | " ORDER BY id ") |
|
| 163 | cursor_energy_db.execute(query, (combined_equipment['id'], start_datetime_utc, )) |
|
| 164 | rows_hourly = cursor_energy_db.fetchall() |
|
| 165 | ||
| 166 | if rows_hourly is None or len(rows_hourly) == 0: |
|
| 167 | print("Step 3: There isn't any energy output data to calculate. ") |
|
| 168 | # continue the for combined equipment loop |
|
| 169 | continue |
|
| 170 | ||
| 171 | energy_dict = dict() |
|
| 172 | energy_category_list = list() |
|
| 173 | end_datetime_utc = start_datetime_utc |
|
| 174 | for row_hourly in rows_hourly: |
|
| 175 | current_datetime_utc = row_hourly[0] |
|
| 176 | energy_category_id = row_hourly[1] |
|
| 177 | ||
| 178 | if energy_category_id not in energy_category_list: |
|
| 179 | energy_category_list.append(energy_category_id) |
|
| 180 | ||
| 181 | actual_value = row_hourly[2] |
|
| 182 | if energy_dict.get(current_datetime_utc) is None: |
|
| 183 | energy_dict[current_datetime_utc] = dict() |
|
| 184 | energy_dict[current_datetime_utc][energy_category_id] = actual_value |
|
| 185 | if current_datetime_utc > end_datetime_utc: |
|
| 186 | end_datetime_utc = current_datetime_utc |
|
| 187 | ||
| 188 | ############################################################################################################ |
|
| 189 | # Step 4: get tariffs |
|
| 190 | ############################################################################################################ |
|
| 191 | print("Step 4: get tariffs") |
|
| 192 | tariff_dict = dict() |
|
| 193 | for energy_category_id in energy_category_list: |
|
| 194 | tariff_dict[energy_category_id] = \ |
|
| 195 | tariff.get_energy_category_tariffs(combined_equipment['cost_center_id'], |
|
| 196 | energy_category_id, |
|
| 197 | start_datetime_utc, |
|
| 198 | end_datetime_utc) |
|
| 199 | ############################################################################################################ |
|
| 200 | # Step 5: calculate billing by multiplying energy with tariff |
|
| 201 | ############################################################################################################ |
|
| 202 | print("Step 5: calculate billing by multiplying energy with tariff") |
|
| 203 | billing_dict = dict() |
|
| 204 | ||
| 205 | if len(energy_dict) > 0: |
|
| 206 | for current_datetime_utc in energy_dict.keys(): |
|
| 207 | billing_dict[current_datetime_utc] = dict() |
|
| 208 | for energy_category_id in energy_category_list: |
|
| 209 | current_tariff = tariff_dict[energy_category_id].get(current_datetime_utc) |
|
| 210 | current_energy = energy_dict[current_datetime_utc].get(energy_category_id) |
|
| 211 | if current_tariff is not None \ |
|
| 212 | and isinstance(current_tariff, Decimal) \ |
|
| 213 | and current_energy is not None \ |
|
| 214 | and isinstance(current_energy, Decimal): |
|
| 215 | billing_dict[current_datetime_utc][energy_category_id] = \ |
|
| 216 | current_energy * current_tariff |
|
| 217 | ||
| 218 | if len(billing_dict[current_datetime_utc]) == 0: |
|
| 219 | del billing_dict[current_datetime_utc] |
|
| 220 | ||
| 221 | ############################################################################################################ |
|
| 222 | # Step 6: save billing data to billing database |
|
| 223 | ############################################################################################################ |
|
| 224 | print("Step 6: save billing data to billing database") |
|
| 225 | ||
| 226 | if len(billing_dict) > 0: |
|
| 227 | try: |
|
| 228 | add_values = (" INSERT INTO tbl_combined_equipment_output_category_hourly " |
|
| 229 | " (combined_equipment_id, " |
|
| 230 | " energy_category_id, " |
|
| 231 | " start_datetime_utc, " |
|
| 232 | " actual_value) " |
|
| 233 | " VALUES ") |
|
| 234 | ||
| 235 | for current_datetime_utc in billing_dict: |
|
| 236 | for energy_category_id in energy_category_list: |
|
| 237 | current_billing = billing_dict[current_datetime_utc].get(energy_category_id) |
|
| 238 | if current_billing is not None and isinstance(current_billing, Decimal): |
|
| 239 | add_values += " (" + str(combined_equipment['id']) + "," |
|
| 240 | add_values += " " + str(energy_category_id) + "," |
|
| 241 | add_values += "'" + current_datetime_utc.isoformat()[0:19] + "'," |
|
| 242 | add_values += str(billing_dict[current_datetime_utc][energy_category_id]) + "), " |
|
| 243 | print("add_values:" + add_values) |
|
| 244 | # trim ", " at the end of string and then execute |
|
| 245 | cursor_billing_db.execute(add_values[:-2]) |
|
| 246 | cnx_billing_db.commit() |
|
| 247 | except Exception as e: |
|
| 248 | logger.error("Error in step 6 of combined_equipment_billing_output_category " + str(e)) |
|
| 249 | # break the for combined_equipment loop |
|
| 250 | break |
|
| 251 | ||
| 252 | # end of for combined equipment loop |
|
| 253 | if cnx_system_db: |
|
| 254 | cnx_system_db.close() |
|
| 255 | if cursor_system_db: |
|
| 256 | cursor_system_db.close() |
|
| 257 | ||
| 258 | if cnx_energy_db: |
|
| 259 | cnx_energy_db.close() |
|
| 260 | if cursor_energy_db: |
|
| 261 | cursor_energy_db.close() |
|
| 262 | ||
| 263 | if cnx_billing_db: |
|
| 264 | cnx_billing_db.close() |
|
| 265 | if cursor_billing_db: |
|
| 266 | cursor_billing_db.close() |
|
| 267 | print("go to sleep 300 seconds...") |
|
| 268 | time.sleep(300) |
|
| 269 | print("wake from sleep, and continue to work...") |
|
| 270 | # end of the outermost while loop |
|
| 271 | ||
| @@ 21-268 (lines=248) @@ | ||
| 18 | ######################################################################################################################## |
|
| 19 | ||
| 20 | ||
| 21 | def main(logger): |
|
| 22 | ||
| 23 | while True: |
|
| 24 | # the outermost while loop |
|
| 25 | ################################################################################################################ |
|
| 26 | # Step 1: get all equipments |
|
| 27 | ################################################################################################################ |
|
| 28 | cnx_system_db = None |
|
| 29 | cursor_system_db = None |
|
| 30 | try: |
|
| 31 | cnx_system_db = mysql.connector.connect(**config.myems_system_db) |
|
| 32 | cursor_system_db = cnx_system_db.cursor() |
|
| 33 | except Exception as e: |
|
| 34 | logger.error("Error in step 1.1 of equipment_billing_input_item " + str(e)) |
|
| 35 | if cursor_system_db: |
|
| 36 | cursor_system_db.close() |
|
| 37 | if cnx_system_db: |
|
| 38 | cnx_system_db.close() |
|
| 39 | # sleep and continue the outermost while loop |
|
| 40 | time.sleep(60) |
|
| 41 | continue |
|
| 42 | ||
| 43 | print("Connected to MyEMS System Database") |
|
| 44 | ||
| 45 | try: |
|
| 46 | cursor_system_db.execute(" SELECT id, name, cost_center_id " |
|
| 47 | " FROM tbl_equipments " |
|
| 48 | " ORDER BY id ") |
|
| 49 | rows_equipments = cursor_system_db.fetchall() |
|
| 50 | ||
| 51 | if rows_equipments is None or len(rows_equipments) == 0: |
|
| 52 | print("Step 1.2: There isn't any equipments. ") |
|
| 53 | if cursor_system_db: |
|
| 54 | cursor_system_db.close() |
|
| 55 | if cnx_system_db: |
|
| 56 | cnx_system_db.close() |
|
| 57 | # sleep and continue the outermost while loop |
|
| 58 | time.sleep(60) |
|
| 59 | continue |
|
| 60 | ||
| 61 | equipment_list = list() |
|
| 62 | for row in rows_equipments: |
|
| 63 | equipment_list.append({"id": row[0], "name": row[1], "cost_center_id": row[2]}) |
|
| 64 | ||
| 65 | except Exception as e: |
|
| 66 | logger.error("Error in step 1.2 of equipment_billing_input_item " + str(e)) |
|
| 67 | if cursor_system_db: |
|
| 68 | cursor_system_db.close() |
|
| 69 | if cnx_system_db: |
|
| 70 | cnx_system_db.close() |
|
| 71 | # sleep and continue the outermost while loop |
|
| 72 | time.sleep(60) |
|
| 73 | continue |
|
| 74 | ||
| 75 | print("Step 1.2: Got all equipments from MyEMS System Database") |
|
| 76 | ||
| 77 | cnx_energy_db = None |
|
| 78 | cursor_energy_db = None |
|
| 79 | try: |
|
| 80 | cnx_energy_db = mysql.connector.connect(**config.myems_energy_db) |
|
| 81 | cursor_energy_db = cnx_energy_db.cursor() |
|
| 82 | except Exception as e: |
|
| 83 | logger.error("Error in step 1.3 of equipment_billing_input_item " + str(e)) |
|
| 84 | if cursor_energy_db: |
|
| 85 | cursor_energy_db.close() |
|
| 86 | if cnx_energy_db: |
|
| 87 | cnx_energy_db.close() |
|
| 88 | ||
| 89 | if cursor_system_db: |
|
| 90 | cursor_system_db.close() |
|
| 91 | if cnx_system_db: |
|
| 92 | cnx_system_db.close() |
|
| 93 | # sleep and continue the outermost while loop |
|
| 94 | time.sleep(60) |
|
| 95 | continue |
|
| 96 | ||
| 97 | print("Connected to MyEMS Energy Database") |
|
| 98 | ||
| 99 | cnx_billing_db = None |
|
| 100 | cursor_billing_db = None |
|
| 101 | try: |
|
| 102 | cnx_billing_db = mysql.connector.connect(**config.myems_billing_db) |
|
| 103 | cursor_billing_db = cnx_billing_db.cursor() |
|
| 104 | except Exception as e: |
|
| 105 | logger.error("Error in step 1.4 of equipment_billing_input_item " + str(e)) |
|
| 106 | if cursor_billing_db: |
|
| 107 | cursor_billing_db.close() |
|
| 108 | if cnx_billing_db: |
|
| 109 | cnx_billing_db.close() |
|
| 110 | ||
| 111 | if cursor_energy_db: |
|
| 112 | cursor_energy_db.close() |
|
| 113 | if cnx_energy_db: |
|
| 114 | cnx_energy_db.close() |
|
| 115 | ||
| 116 | if cursor_system_db: |
|
| 117 | cursor_system_db.close() |
|
| 118 | if cnx_system_db: |
|
| 119 | cnx_system_db.close() |
|
| 120 | # sleep and continue the outermost while loop |
|
| 121 | time.sleep(60) |
|
| 122 | continue |
|
| 123 | ||
| 124 | print("Connected to MyEMS Billing Database") |
|
| 125 | ||
| 126 | for equipment in equipment_list: |
|
| 127 | ||
| 128 | ############################################################################################################ |
|
| 129 | # Step 2: get the latest start_datetime_utc |
|
| 130 | ############################################################################################################ |
|
| 131 | print("Step 2: get the latest start_datetime_utc from billing database for " + equipment['name']) |
|
| 132 | try: |
|
| 133 | cursor_billing_db.execute(" SELECT MAX(start_datetime_utc) " |
|
| 134 | " FROM tbl_equipment_input_item_hourly " |
|
| 135 | " WHERE equipment_id = %s ", |
|
| 136 | (equipment['id'], )) |
|
| 137 | row_datetime = cursor_billing_db.fetchone() |
|
| 138 | start_datetime_utc = datetime.strptime(config.start_datetime_utc, '%Y-%m-%d %H:%M:%S') |
|
| 139 | start_datetime_utc = start_datetime_utc.replace(minute=0, second=0, microsecond=0, tzinfo=None) |
|
| 140 | ||
| 141 | if row_datetime is not None and len(row_datetime) > 0 and isinstance(row_datetime[0], datetime): |
|
| 142 | # replace second and microsecond with 0 |
|
| 143 | # note: do not replace minute in case of calculating in half hourly |
|
| 144 | start_datetime_utc = row_datetime[0].replace(second=0, microsecond=0, tzinfo=None) |
|
| 145 | # start from the next time slot |
|
| 146 | start_datetime_utc += timedelta(minutes=config.minutes_to_count) |
|
| 147 | ||
| 148 | print("start_datetime_utc: " + start_datetime_utc.isoformat()[0:19]) |
|
| 149 | except Exception as e: |
|
| 150 | logger.error("Error in step 2 of equipment_billing_input_item " + str(e)) |
|
| 151 | # break the for equipment loop |
|
| 152 | break |
|
| 153 | ||
| 154 | ############################################################################################################ |
|
| 155 | # Step 3: get all energy input data since the latest start_datetime_utc |
|
| 156 | ############################################################################################################ |
|
| 157 | print("Step 3: get all energy input data since the latest start_datetime_utc") |
|
| 158 | ||
| 159 | query = (" SELECT start_datetime_utc, energy_item_id, actual_value " |
|
| 160 | " FROM tbl_equipment_input_item_hourly " |
|
| 161 | " WHERE equipment_id = %s AND start_datetime_utc >= %s " |
|
| 162 | " ORDER BY id ") |
|
| 163 | cursor_energy_db.execute(query, (equipment['id'], start_datetime_utc, )) |
|
| 164 | rows_hourly = cursor_energy_db.fetchall() |
|
| 165 | ||
| 166 | if rows_hourly is None or len(rows_hourly) == 0: |
|
| 167 | print("Step 3: There isn't any energy input data to calculate. ") |
|
| 168 | # continue the for equipment loop |
|
| 169 | continue |
|
| 170 | ||
| 171 | energy_dict = dict() |
|
| 172 | energy_item_list = list() |
|
| 173 | end_datetime_utc = start_datetime_utc |
|
| 174 | for row_hourly in rows_hourly: |
|
| 175 | current_datetime_utc = row_hourly[0] |
|
| 176 | energy_item_id = row_hourly[1] |
|
| 177 | ||
| 178 | if energy_item_id not in energy_item_list: |
|
| 179 | energy_item_list.append(energy_item_id) |
|
| 180 | ||
| 181 | actual_value = row_hourly[2] |
|
| 182 | if energy_dict.get(current_datetime_utc) is None: |
|
| 183 | energy_dict[current_datetime_utc] = dict() |
|
| 184 | energy_dict[current_datetime_utc][energy_item_id] = actual_value |
|
| 185 | if current_datetime_utc > end_datetime_utc: |
|
| 186 | end_datetime_utc = current_datetime_utc |
|
| 187 | ||
| 188 | ############################################################################################################ |
|
| 189 | # Step 4: get tariffs |
|
| 190 | ############################################################################################################ |
|
| 191 | print("Step 4: get tariffs") |
|
| 192 | tariff_dict = dict() |
|
| 193 | for energy_item_id in energy_item_list: |
|
| 194 | tariff_dict[energy_item_id] = tariff.get_energy_item_tariffs(equipment['cost_center_id'], |
|
| 195 | energy_item_id, |
|
| 196 | start_datetime_utc, |
|
| 197 | end_datetime_utc) |
|
| 198 | ############################################################################################################ |
|
| 199 | # Step 5: calculate billing by multiplying energy with tariff |
|
| 200 | ############################################################################################################ |
|
| 201 | print("Step 5: calculate billing by multiplying energy with tariff") |
|
| 202 | billing_dict = dict() |
|
| 203 | ||
| 204 | if len(energy_dict) > 0: |
|
| 205 | for current_datetime_utc in energy_dict.keys(): |
|
| 206 | billing_dict[current_datetime_utc] = dict() |
|
| 207 | for energy_item_id in energy_item_list: |
|
| 208 | current_tariff = tariff_dict[energy_item_id].get(current_datetime_utc) |
|
| 209 | current_energy = energy_dict[current_datetime_utc].get(energy_item_id) |
|
| 210 | if current_tariff is not None \ |
|
| 211 | and isinstance(current_tariff, Decimal) \ |
|
| 212 | and current_energy is not None \ |
|
| 213 | and isinstance(current_energy, Decimal): |
|
| 214 | billing_dict[current_datetime_utc][energy_item_id] = \ |
|
| 215 | current_energy * current_tariff |
|
| 216 | ||
| 217 | if len(billing_dict[current_datetime_utc]) == 0: |
|
| 218 | del billing_dict[current_datetime_utc] |
|
| 219 | ||
| 220 | ############################################################################################################ |
|
| 221 | # Step 6: save billing data to billing database |
|
| 222 | ############################################################################################################ |
|
| 223 | print("Step 6: save billing data to billing database") |
|
| 224 | ||
| 225 | if len(billing_dict) > 0: |
|
| 226 | try: |
|
| 227 | add_values = (" INSERT INTO tbl_equipment_input_item_hourly " |
|
| 228 | " (equipment_id, " |
|
| 229 | " energy_item_id, " |
|
| 230 | " start_datetime_utc, " |
|
| 231 | " actual_value) " |
|
| 232 | " VALUES ") |
|
| 233 | ||
| 234 | for current_datetime_utc in billing_dict: |
|
| 235 | for energy_item_id in energy_item_list: |
|
| 236 | current_billing = billing_dict[current_datetime_utc].get(energy_item_id) |
|
| 237 | if current_billing is not None and isinstance(current_billing, Decimal): |
|
| 238 | add_values += " (" + str(equipment['id']) + "," |
|
| 239 | add_values += " " + str(energy_item_id) + "," |
|
| 240 | add_values += "'" + current_datetime_utc.isoformat()[0:19] + "'," |
|
| 241 | add_values += str(billing_dict[current_datetime_utc][energy_item_id]) + "), " |
|
| 242 | print("add_values:" + add_values) |
|
| 243 | # trim ", " at the end of string and then execute |
|
| 244 | cursor_billing_db.execute(add_values[:-2]) |
|
| 245 | cnx_billing_db.commit() |
|
| 246 | except Exception as e: |
|
| 247 | logger.error("Error in step 6 of equipment_billing_input_item " + str(e)) |
|
| 248 | # break the for equipment loop |
|
| 249 | break |
|
| 250 | ||
| 251 | # end of for equipment loop |
|
| 252 | if cnx_system_db: |
|
| 253 | cnx_system_db.close() |
|
| 254 | if cursor_system_db: |
|
| 255 | cursor_system_db.close() |
|
| 256 | ||
| 257 | if cnx_energy_db: |
|
| 258 | cnx_energy_db.close() |
|
| 259 | if cursor_energy_db: |
|
| 260 | cursor_energy_db.close() |
|
| 261 | ||
| 262 | if cnx_billing_db: |
|
| 263 | cnx_billing_db.close() |
|
| 264 | if cursor_billing_db: |
|
| 265 | cursor_billing_db.close() |
|
| 266 | print("go to sleep 300 seconds...") |
|
| 267 | time.sleep(300) |
|
| 268 | print("wake from sleep, and continue to work...") |
|
| 269 | # end of the outermost while loop |
|
| 270 | ||
| @@ 21-268 (lines=248) @@ | ||
| 18 | ######################################################################################################################## |
|
| 19 | ||
| 20 | ||
| 21 | def main(logger): |
|
| 22 | ||
| 23 | while True: |
|
| 24 | # the outermost while loop |
|
| 25 | ################################################################################################################ |
|
| 26 | # Step 1: get all spaces |
|
| 27 | ################################################################################################################ |
|
| 28 | cnx_system_db = None |
|
| 29 | cursor_system_db = None |
|
| 30 | try: |
|
| 31 | cnx_system_db = mysql.connector.connect(**config.myems_system_db) |
|
| 32 | cursor_system_db = cnx_system_db.cursor() |
|
| 33 | except Exception as e: |
|
| 34 | logger.error("Error in step 1.1 of space_billing_output_category " + str(e)) |
|
| 35 | if cursor_system_db: |
|
| 36 | cursor_system_db.close() |
|
| 37 | if cnx_system_db: |
|
| 38 | cnx_system_db.close() |
|
| 39 | # sleep and continue the outermost while loop |
|
| 40 | time.sleep(60) |
|
| 41 | continue |
|
| 42 | ||
| 43 | print("Connected to MyEMS System Database") |
|
| 44 | ||
| 45 | try: |
|
| 46 | cursor_system_db.execute(" SELECT id, name, cost_center_id " |
|
| 47 | " FROM tbl_spaces " |
|
| 48 | " ORDER BY id ") |
|
| 49 | rows_spaces = cursor_system_db.fetchall() |
|
| 50 | ||
| 51 | if rows_spaces is None or len(rows_spaces) == 0: |
|
| 52 | print("Step 1.2: There isn't any spaces. ") |
|
| 53 | if cursor_system_db: |
|
| 54 | cursor_system_db.close() |
|
| 55 | if cnx_system_db: |
|
| 56 | cnx_system_db.close() |
|
| 57 | # sleep and continue the outermost while loop |
|
| 58 | time.sleep(60) |
|
| 59 | continue |
|
| 60 | ||
| 61 | space_list = list() |
|
| 62 | for row in rows_spaces: |
|
| 63 | space_list.append({"id": row[0], "name": row[1], "cost_center_id": row[2]}) |
|
| 64 | ||
| 65 | except Exception as e: |
|
| 66 | logger.error("Error in step 1.2 of space_billing_output_category " + str(e)) |
|
| 67 | if cursor_system_db: |
|
| 68 | cursor_system_db.close() |
|
| 69 | if cnx_system_db: |
|
| 70 | cnx_system_db.close() |
|
| 71 | # sleep and continue the outermost while loop |
|
| 72 | time.sleep(60) |
|
| 73 | continue |
|
| 74 | ||
| 75 | print("Step 1.2: Got all spaces from MyEMS System Database") |
|
| 76 | ||
| 77 | cnx_energy_db = None |
|
| 78 | cursor_energy_db = None |
|
| 79 | try: |
|
| 80 | cnx_energy_db = mysql.connector.connect(**config.myems_energy_db) |
|
| 81 | cursor_energy_db = cnx_energy_db.cursor() |
|
| 82 | except Exception as e: |
|
| 83 | logger.error("Error in step 1.3 of space_billing_output_category " + str(e)) |
|
| 84 | if cursor_energy_db: |
|
| 85 | cursor_energy_db.close() |
|
| 86 | if cnx_energy_db: |
|
| 87 | cnx_energy_db.close() |
|
| 88 | ||
| 89 | if cursor_system_db: |
|
| 90 | cursor_system_db.close() |
|
| 91 | if cnx_system_db: |
|
| 92 | cnx_system_db.close() |
|
| 93 | # sleep and continue the outermost while loop |
|
| 94 | time.sleep(60) |
|
| 95 | continue |
|
| 96 | ||
| 97 | print("Connected to MyEMS Energy Database") |
|
| 98 | ||
| 99 | cnx_billing_db = None |
|
| 100 | cursor_billing_db = None |
|
| 101 | try: |
|
| 102 | cnx_billing_db = mysql.connector.connect(**config.myems_billing_db) |
|
| 103 | cursor_billing_db = cnx_billing_db.cursor() |
|
| 104 | except Exception as e: |
|
| 105 | logger.error("Error in step 1.4 of space_billing_output_category " + str(e)) |
|
| 106 | if cursor_billing_db: |
|
| 107 | cursor_billing_db.close() |
|
| 108 | if cnx_billing_db: |
|
| 109 | cnx_billing_db.close() |
|
| 110 | ||
| 111 | if cursor_energy_db: |
|
| 112 | cursor_energy_db.close() |
|
| 113 | if cnx_energy_db: |
|
| 114 | cnx_energy_db.close() |
|
| 115 | ||
| 116 | if cursor_system_db: |
|
| 117 | cursor_system_db.close() |
|
| 118 | if cnx_system_db: |
|
| 119 | cnx_system_db.close() |
|
| 120 | # sleep and continue the outermost while loop |
|
| 121 | time.sleep(60) |
|
| 122 | continue |
|
| 123 | ||
| 124 | print("Connected to MyEMS Billing Database") |
|
| 125 | ||
| 126 | for space in space_list: |
|
| 127 | ||
| 128 | ############################################################################################################ |
|
| 129 | # Step 2: get the latest start_datetime_utc |
|
| 130 | ############################################################################################################ |
|
| 131 | print("Step 2: get the latest start_datetime_utc from billing database for " + space['name']) |
|
| 132 | try: |
|
| 133 | cursor_billing_db.execute(" SELECT MAX(start_datetime_utc) " |
|
| 134 | " FROM tbl_space_output_category_hourly " |
|
| 135 | " WHERE space_id = %s ", |
|
| 136 | (space['id'], )) |
|
| 137 | row_datetime = cursor_billing_db.fetchone() |
|
| 138 | start_datetime_utc = datetime.strptime(config.start_datetime_utc, '%Y-%m-%d %H:%M:%S') |
|
| 139 | start_datetime_utc = start_datetime_utc.replace(minute=0, second=0, microsecond=0, tzinfo=None) |
|
| 140 | ||
| 141 | if row_datetime is not None and len(row_datetime) > 0 and isinstance(row_datetime[0], datetime): |
|
| 142 | # replace second and microsecond with 0 |
|
| 143 | # note: do not replace minute in case of calculating in half hourly |
|
| 144 | start_datetime_utc = row_datetime[0].replace(second=0, microsecond=0, tzinfo=None) |
|
| 145 | # start from the next time slot |
|
| 146 | start_datetime_utc += timedelta(minutes=config.minutes_to_count) |
|
| 147 | ||
| 148 | print("start_datetime_utc: " + start_datetime_utc.isoformat()[0:19]) |
|
| 149 | except Exception as e: |
|
| 150 | logger.error("Error in step 2 of space_billing_output_category " + str(e)) |
|
| 151 | # break the for space loop |
|
| 152 | break |
|
| 153 | ||
| 154 | ############################################################################################################ |
|
| 155 | # Step 3: get all energy output data since the latest start_datetime_utc |
|
| 156 | ############################################################################################################ |
|
| 157 | print("Step 3: get all energy output data since the latest start_datetime_utc") |
|
| 158 | ||
| 159 | query = (" SELECT start_datetime_utc, energy_category_id, actual_value " |
|
| 160 | " FROM tbl_space_output_category_hourly " |
|
| 161 | " WHERE space_id = %s AND start_datetime_utc >= %s " |
|
| 162 | " ORDER BY id ") |
|
| 163 | cursor_energy_db.execute(query, (space['id'], start_datetime_utc, )) |
|
| 164 | rows_hourly = cursor_energy_db.fetchall() |
|
| 165 | ||
| 166 | if rows_hourly is None or len(rows_hourly) == 0: |
|
| 167 | print("Step 3: There isn't any energy output data to calculate. ") |
|
| 168 | # continue the for space loop |
|
| 169 | continue |
|
| 170 | ||
| 171 | energy_dict = dict() |
|
| 172 | energy_category_list = list() |
|
| 173 | end_datetime_utc = start_datetime_utc |
|
| 174 | for row_hourly in rows_hourly: |
|
| 175 | current_datetime_utc = row_hourly[0] |
|
| 176 | energy_category_id = row_hourly[1] |
|
| 177 | ||
| 178 | if energy_category_id not in energy_category_list: |
|
| 179 | energy_category_list.append(energy_category_id) |
|
| 180 | ||
| 181 | actual_value = row_hourly[2] |
|
| 182 | if energy_dict.get(current_datetime_utc) is None: |
|
| 183 | energy_dict[current_datetime_utc] = dict() |
|
| 184 | energy_dict[current_datetime_utc][energy_category_id] = actual_value |
|
| 185 | if current_datetime_utc > end_datetime_utc: |
|
| 186 | end_datetime_utc = current_datetime_utc |
|
| 187 | ||
| 188 | ############################################################################################################ |
|
| 189 | # Step 4: get tariffs |
|
| 190 | ############################################################################################################ |
|
| 191 | print("Step 4: get tariffs") |
|
| 192 | tariff_dict = dict() |
|
| 193 | for energy_category_id in energy_category_list: |
|
| 194 | tariff_dict[energy_category_id] = tariff.get_energy_category_tariffs(space['cost_center_id'], |
|
| 195 | energy_category_id, |
|
| 196 | start_datetime_utc, |
|
| 197 | end_datetime_utc) |
|
| 198 | ############################################################################################################ |
|
| 199 | # Step 5: calculate billing by multiplying energy with tariff |
|
| 200 | ############################################################################################################ |
|
| 201 | print("Step 5: calculate billing by multiplying energy with tariff") |
|
| 202 | billing_dict = dict() |
|
| 203 | ||
| 204 | if len(energy_dict) > 0: |
|
| 205 | for current_datetime_utc in energy_dict.keys(): |
|
| 206 | billing_dict[current_datetime_utc] = dict() |
|
| 207 | for energy_category_id in energy_category_list: |
|
| 208 | current_tariff = tariff_dict[energy_category_id].get(current_datetime_utc) |
|
| 209 | current_energy = energy_dict[current_datetime_utc].get(energy_category_id) |
|
| 210 | if current_tariff is not None \ |
|
| 211 | and isinstance(current_tariff, Decimal) \ |
|
| 212 | and current_energy is not None \ |
|
| 213 | and isinstance(current_energy, Decimal): |
|
| 214 | billing_dict[current_datetime_utc][energy_category_id] = \ |
|
| 215 | current_energy * current_tariff |
|
| 216 | ||
| 217 | if len(billing_dict[current_datetime_utc]) == 0: |
|
| 218 | del billing_dict[current_datetime_utc] |
|
| 219 | ||
| 220 | ############################################################################################################ |
|
| 221 | # Step 6: save billing data to billing database |
|
| 222 | ############################################################################################################ |
|
| 223 | print("Step 6: save billing data to billing database") |
|
| 224 | ||
| 225 | if len(billing_dict) > 0: |
|
| 226 | try: |
|
| 227 | add_values = (" INSERT INTO tbl_space_output_category_hourly " |
|
| 228 | " (space_id, " |
|
| 229 | " energy_category_id, " |
|
| 230 | " start_datetime_utc, " |
|
| 231 | " actual_value) " |
|
| 232 | " VALUES ") |
|
| 233 | ||
| 234 | for current_datetime_utc in billing_dict: |
|
| 235 | for energy_category_id in energy_category_list: |
|
| 236 | current_billing = billing_dict[current_datetime_utc].get(energy_category_id) |
|
| 237 | if current_billing is not None and isinstance(current_billing, Decimal): |
|
| 238 | add_values += " (" + str(space['id']) + "," |
|
| 239 | add_values += " " + str(energy_category_id) + "," |
|
| 240 | add_values += "'" + current_datetime_utc.isoformat()[0:19] + "'," |
|
| 241 | add_values += str(billing_dict[current_datetime_utc][energy_category_id]) + "), " |
|
| 242 | print("add_values:" + add_values) |
|
| 243 | # trim ", " at the end of string and then execute |
|
| 244 | cursor_billing_db.execute(add_values[:-2]) |
|
| 245 | cnx_billing_db.commit() |
|
| 246 | except Exception as e: |
|
| 247 | logger.error("Error in step 6 of space_billing_output_category " + str(e)) |
|
| 248 | # break the for space loop |
|
| 249 | break |
|
| 250 | ||
| 251 | # end of for space loop |
|
| 252 | if cnx_system_db: |
|
| 253 | cnx_system_db.close() |
|
| 254 | if cursor_system_db: |
|
| 255 | cursor_system_db.close() |
|
| 256 | ||
| 257 | if cnx_energy_db: |
|
| 258 | cnx_energy_db.close() |
|
| 259 | if cursor_energy_db: |
|
| 260 | cursor_energy_db.close() |
|
| 261 | ||
| 262 | if cnx_billing_db: |
|
| 263 | cnx_billing_db.close() |
|
| 264 | if cursor_billing_db: |
|
| 265 | cursor_billing_db.close() |
|
| 266 | print("go to sleep 300 seconds...") |
|
| 267 | time.sleep(300) |
|
| 268 | print("wake from sleep, and continue to work...") |
|
| 269 | # end of the outermost while loop |
|
| 270 | ||
| @@ 21-268 (lines=248) @@ | ||
| 18 | ######################################################################################################################## |
|
| 19 | ||
| 20 | ||
| 21 | def main(logger): |
|
| 22 | ||
| 23 | while True: |
|
| 24 | # the outermost while loop |
|
| 25 | ################################################################################################################ |
|
| 26 | # Step 1: get all shopfloors |
|
| 27 | ################################################################################################################ |
|
| 28 | cnx_system_db = None |
|
| 29 | cursor_system_db = None |
|
| 30 | try: |
|
| 31 | cnx_system_db = mysql.connector.connect(**config.myems_system_db) |
|
| 32 | cursor_system_db = cnx_system_db.cursor() |
|
| 33 | except Exception as e: |
|
| 34 | logger.error("Error in step 1.1 of shopfloor_billing_input_category " + str(e)) |
|
| 35 | if cursor_system_db: |
|
| 36 | cursor_system_db.close() |
|
| 37 | if cnx_system_db: |
|
| 38 | cnx_system_db.close() |
|
| 39 | # sleep and continue the outermost while loop |
|
| 40 | time.sleep(60) |
|
| 41 | continue |
|
| 42 | ||
| 43 | print("Connected to MyEMS System Database") |
|
| 44 | ||
| 45 | try: |
|
| 46 | cursor_system_db.execute(" SELECT id, name, cost_center_id " |
|
| 47 | " FROM tbl_shopfloors " |
|
| 48 | " ORDER BY id ") |
|
| 49 | rows_shopfloors = cursor_system_db.fetchall() |
|
| 50 | ||
| 51 | if rows_shopfloors is None or len(rows_shopfloors) == 0: |
|
| 52 | print("Step 1.2: There isn't any shopfloors. ") |
|
| 53 | if cursor_system_db: |
|
| 54 | cursor_system_db.close() |
|
| 55 | if cnx_system_db: |
|
| 56 | cnx_system_db.close() |
|
| 57 | # sleep and continue the outermost while loop |
|
| 58 | time.sleep(60) |
|
| 59 | continue |
|
| 60 | ||
| 61 | shopfloor_list = list() |
|
| 62 | for row in rows_shopfloors: |
|
| 63 | shopfloor_list.append({"id": row[0], "name": row[1], "cost_center_id": row[2]}) |
|
| 64 | ||
| 65 | except Exception as e: |
|
| 66 | logger.error("Error in step 1.2 of shopfloor_billing_input_category " + str(e)) |
|
| 67 | if cursor_system_db: |
|
| 68 | cursor_system_db.close() |
|
| 69 | if cnx_system_db: |
|
| 70 | cnx_system_db.close() |
|
| 71 | # sleep and continue the outermost while loop |
|
| 72 | time.sleep(60) |
|
| 73 | continue |
|
| 74 | ||
| 75 | print("Step 1.2: Got all shopfloors from MyEMS System Database") |
|
| 76 | ||
| 77 | cnx_energy_db = None |
|
| 78 | cursor_energy_db = None |
|
| 79 | try: |
|
| 80 | cnx_energy_db = mysql.connector.connect(**config.myems_energy_db) |
|
| 81 | cursor_energy_db = cnx_energy_db.cursor() |
|
| 82 | except Exception as e: |
|
| 83 | logger.error("Error in step 1.3 of shopfloor_billing_input_category " + str(e)) |
|
| 84 | if cursor_energy_db: |
|
| 85 | cursor_energy_db.close() |
|
| 86 | if cnx_energy_db: |
|
| 87 | cnx_energy_db.close() |
|
| 88 | ||
| 89 | if cursor_system_db: |
|
| 90 | cursor_system_db.close() |
|
| 91 | if cnx_system_db: |
|
| 92 | cnx_system_db.close() |
|
| 93 | # sleep and continue the outermost while loop |
|
| 94 | time.sleep(60) |
|
| 95 | continue |
|
| 96 | ||
| 97 | print("Connected to MyEMS Energy Database") |
|
| 98 | ||
| 99 | cnx_billing_db = None |
|
| 100 | cursor_billing_db = None |
|
| 101 | try: |
|
| 102 | cnx_billing_db = mysql.connector.connect(**config.myems_billing_db) |
|
| 103 | cursor_billing_db = cnx_billing_db.cursor() |
|
| 104 | except Exception as e: |
|
| 105 | logger.error("Error in step 1.4 of shopfloor_billing_input_category " + str(e)) |
|
| 106 | if cursor_billing_db: |
|
| 107 | cursor_billing_db.close() |
|
| 108 | if cnx_billing_db: |
|
| 109 | cnx_billing_db.close() |
|
| 110 | ||
| 111 | if cursor_energy_db: |
|
| 112 | cursor_energy_db.close() |
|
| 113 | if cnx_energy_db: |
|
| 114 | cnx_energy_db.close() |
|
| 115 | ||
| 116 | if cursor_system_db: |
|
| 117 | cursor_system_db.close() |
|
| 118 | if cnx_system_db: |
|
| 119 | cnx_system_db.close() |
|
| 120 | # sleep and continue the outermost while loop |
|
| 121 | time.sleep(60) |
|
| 122 | continue |
|
| 123 | ||
| 124 | print("Connected to MyEMS Billing Database") |
|
| 125 | ||
| 126 | for shopfloor in shopfloor_list: |
|
| 127 | ||
| 128 | ############################################################################################################ |
|
| 129 | # Step 2: get the latest start_datetime_utc |
|
| 130 | ############################################################################################################ |
|
| 131 | print("Step 2: get the latest start_datetime_utc from billing database for " + shopfloor['name']) |
|
| 132 | try: |
|
| 133 | cursor_billing_db.execute(" SELECT MAX(start_datetime_utc) " |
|
| 134 | " FROM tbl_shopfloor_input_category_hourly " |
|
| 135 | " WHERE shopfloor_id = %s ", |
|
| 136 | (shopfloor['id'], )) |
|
| 137 | row_datetime = cursor_billing_db.fetchone() |
|
| 138 | start_datetime_utc = datetime.strptime(config.start_datetime_utc, '%Y-%m-%d %H:%M:%S') |
|
| 139 | start_datetime_utc = start_datetime_utc.replace(minute=0, second=0, microsecond=0, tzinfo=None) |
|
| 140 | ||
| 141 | if row_datetime is not None and len(row_datetime) > 0 and isinstance(row_datetime[0], datetime): |
|
| 142 | # replace second and microsecond with 0 |
|
| 143 | # note: do not replace minute in case of calculating in half hourly |
|
| 144 | start_datetime_utc = row_datetime[0].replace(second=0, microsecond=0, tzinfo=None) |
|
| 145 | # start from the next time slot |
|
| 146 | start_datetime_utc += timedelta(minutes=config.minutes_to_count) |
|
| 147 | ||
| 148 | print("start_datetime_utc: " + start_datetime_utc.isoformat()[0:19]) |
|
| 149 | except Exception as e: |
|
| 150 | logger.error("Error in step 2 of shopfloor_billing_input_category " + str(e)) |
|
| 151 | # break the for shopfloor loop |
|
| 152 | break |
|
| 153 | ||
| 154 | ############################################################################################################ |
|
| 155 | # Step 3: get all energy input data since the latest start_datetime_utc |
|
| 156 | ############################################################################################################ |
|
| 157 | print("Step 3: get all energy input data since the latest start_datetime_utc") |
|
| 158 | ||
| 159 | query = (" SELECT start_datetime_utc, energy_category_id, actual_value " |
|
| 160 | " FROM tbl_shopfloor_input_category_hourly " |
|
| 161 | " WHERE shopfloor_id = %s AND start_datetime_utc >= %s " |
|
| 162 | " ORDER BY id ") |
|
| 163 | cursor_energy_db.execute(query, (shopfloor['id'], start_datetime_utc, )) |
|
| 164 | rows_hourly = cursor_energy_db.fetchall() |
|
| 165 | ||
| 166 | if rows_hourly is None or len(rows_hourly) == 0: |
|
| 167 | print("Step 3: There isn't any energy input data to calculate. ") |
|
| 168 | # continue the for shopfloor loop |
|
| 169 | continue |
|
| 170 | ||
| 171 | energy_dict = dict() |
|
| 172 | energy_category_list = list() |
|
| 173 | end_datetime_utc = start_datetime_utc |
|
| 174 | for row_hourly in rows_hourly: |
|
| 175 | current_datetime_utc = row_hourly[0] |
|
| 176 | energy_category_id = row_hourly[1] |
|
| 177 | ||
| 178 | if energy_category_id not in energy_category_list: |
|
| 179 | energy_category_list.append(energy_category_id) |
|
| 180 | ||
| 181 | actual_value = row_hourly[2] |
|
| 182 | if energy_dict.get(current_datetime_utc) is None: |
|
| 183 | energy_dict[current_datetime_utc] = dict() |
|
| 184 | energy_dict[current_datetime_utc][energy_category_id] = actual_value |
|
| 185 | if current_datetime_utc > end_datetime_utc: |
|
| 186 | end_datetime_utc = current_datetime_utc |
|
| 187 | ||
| 188 | ############################################################################################################ |
|
| 189 | # Step 4: get tariffs |
|
| 190 | ############################################################################################################ |
|
| 191 | print("Step 4: get tariffs") |
|
| 192 | tariff_dict = dict() |
|
| 193 | for energy_category_id in energy_category_list: |
|
| 194 | tariff_dict[energy_category_id] = tariff.get_energy_category_tariffs(shopfloor['cost_center_id'], |
|
| 195 | energy_category_id, |
|
| 196 | start_datetime_utc, |
|
| 197 | end_datetime_utc) |
|
| 198 | ############################################################################################################ |
|
| 199 | # Step 5: calculate billing by multiplying energy with tariff |
|
| 200 | ############################################################################################################ |
|
| 201 | print("Step 5: calculate billing by multiplying energy with tariff") |
|
| 202 | billing_dict = dict() |
|
| 203 | ||
| 204 | if len(energy_dict) > 0: |
|
| 205 | for current_datetime_utc in energy_dict.keys(): |
|
| 206 | billing_dict[current_datetime_utc] = dict() |
|
| 207 | for energy_category_id in energy_category_list: |
|
| 208 | current_tariff = tariff_dict[energy_category_id].get(current_datetime_utc) |
|
| 209 | current_energy = energy_dict[current_datetime_utc].get(energy_category_id) |
|
| 210 | if current_tariff is not None \ |
|
| 211 | and isinstance(current_tariff, Decimal) \ |
|
| 212 | and current_energy is not None \ |
|
| 213 | and isinstance(current_energy, Decimal): |
|
| 214 | billing_dict[current_datetime_utc][energy_category_id] = \ |
|
| 215 | current_energy * current_tariff |
|
| 216 | ||
| 217 | if len(billing_dict[current_datetime_utc]) == 0: |
|
| 218 | del billing_dict[current_datetime_utc] |
|
| 219 | ||
| 220 | ############################################################################################################ |
|
| 221 | # Step 6: save billing data to billing database |
|
| 222 | ############################################################################################################ |
|
| 223 | print("Step 6: save billing data to billing database") |
|
| 224 | ||
| 225 | if len(billing_dict) > 0: |
|
| 226 | try: |
|
| 227 | add_values = (" INSERT INTO tbl_shopfloor_input_category_hourly " |
|
| 228 | " (shopfloor_id, " |
|
| 229 | " energy_category_id, " |
|
| 230 | " start_datetime_utc, " |
|
| 231 | " actual_value) " |
|
| 232 | " VALUES ") |
|
| 233 | ||
| 234 | for current_datetime_utc in billing_dict: |
|
| 235 | for energy_category_id in energy_category_list: |
|
| 236 | current_billing = billing_dict[current_datetime_utc].get(energy_category_id) |
|
| 237 | if current_billing is not None and isinstance(current_billing, Decimal): |
|
| 238 | add_values += " (" + str(shopfloor['id']) + "," |
|
| 239 | add_values += " " + str(energy_category_id) + "," |
|
| 240 | add_values += "'" + current_datetime_utc.isoformat()[0:19] + "'," |
|
| 241 | add_values += str(billing_dict[current_datetime_utc][energy_category_id]) + "), " |
|
| 242 | print("add_values:" + add_values) |
|
| 243 | # trim ", " at the end of string and then execute |
|
| 244 | cursor_billing_db.execute(add_values[:-2]) |
|
| 245 | cnx_billing_db.commit() |
|
| 246 | except Exception as e: |
|
| 247 | logger.error("Error in step 6 of shopfloor_billing_input_category " + str(e)) |
|
| 248 | # break the for shopfloor loop |
|
| 249 | break |
|
| 250 | ||
| 251 | # end of for shopfloor loop |
|
| 252 | if cnx_system_db: |
|
| 253 | cnx_system_db.close() |
|
| 254 | if cursor_system_db: |
|
| 255 | cursor_system_db.close() |
|
| 256 | ||
| 257 | if cnx_energy_db: |
|
| 258 | cnx_energy_db.close() |
|
| 259 | if cursor_energy_db: |
|
| 260 | cursor_energy_db.close() |
|
| 261 | ||
| 262 | if cnx_billing_db: |
|
| 263 | cnx_billing_db.close() |
|
| 264 | if cursor_billing_db: |
|
| 265 | cursor_billing_db.close() |
|
| 266 | print("go to sleep 300 seconds...") |
|
| 267 | time.sleep(300) |
|
| 268 | print("wake from sleep, and continue to work...") |
|
| 269 | # end of the outermost while loop |
|
| 270 | ||
| @@ 21-268 (lines=248) @@ | ||
| 18 | ######################################################################################################################## |
|
| 19 | ||
| 20 | ||
| 21 | def main(logger): |
|
| 22 | ||
| 23 | while True: |
|
| 24 | # the outermost while loop |
|
| 25 | ################################################################################################################ |
|
| 26 | # Step 1: get all equipments |
|
| 27 | ################################################################################################################ |
|
| 28 | cnx_system_db = None |
|
| 29 | cursor_system_db = None |
|
| 30 | try: |
|
| 31 | cnx_system_db = mysql.connector.connect(**config.myems_system_db) |
|
| 32 | cursor_system_db = cnx_system_db.cursor() |
|
| 33 | except Exception as e: |
|
| 34 | logger.error("Error in step 1.1 of equipment_billing_input_category " + str(e)) |
|
| 35 | if cursor_system_db: |
|
| 36 | cursor_system_db.close() |
|
| 37 | if cnx_system_db: |
|
| 38 | cnx_system_db.close() |
|
| 39 | # sleep and continue the outermost while loop |
|
| 40 | time.sleep(60) |
|
| 41 | continue |
|
| 42 | ||
| 43 | print("Connected to MyEMS System Database") |
|
| 44 | ||
| 45 | try: |
|
| 46 | cursor_system_db.execute(" SELECT id, name, cost_center_id " |
|
| 47 | " FROM tbl_equipments " |
|
| 48 | " ORDER BY id ") |
|
| 49 | rows_equipments = cursor_system_db.fetchall() |
|
| 50 | ||
| 51 | if rows_equipments is None or len(rows_equipments) == 0: |
|
| 52 | print("Step 1.2: There isn't any equipments. ") |
|
| 53 | if cursor_system_db: |
|
| 54 | cursor_system_db.close() |
|
| 55 | if cnx_system_db: |
|
| 56 | cnx_system_db.close() |
|
| 57 | # sleep and continue the outermost while loop |
|
| 58 | time.sleep(60) |
|
| 59 | continue |
|
| 60 | ||
| 61 | equipment_list = list() |
|
| 62 | for row in rows_equipments: |
|
| 63 | equipment_list.append({"id": row[0], "name": row[1], "cost_center_id": row[2]}) |
|
| 64 | ||
| 65 | except Exception as e: |
|
| 66 | logger.error("Error in step 1.2 of equipment_billing_output_category " + str(e)) |
|
| 67 | if cursor_system_db: |
|
| 68 | cursor_system_db.close() |
|
| 69 | if cnx_system_db: |
|
| 70 | cnx_system_db.close() |
|
| 71 | # sleep and continue the outermost while loop |
|
| 72 | time.sleep(60) |
|
| 73 | continue |
|
| 74 | ||
| 75 | print("Step 1.2: Got all equipments from MyEMS System Database") |
|
| 76 | ||
| 77 | cnx_energy_db = None |
|
| 78 | cursor_energy_db = None |
|
| 79 | try: |
|
| 80 | cnx_energy_db = mysql.connector.connect(**config.myems_energy_db) |
|
| 81 | cursor_energy_db = cnx_energy_db.cursor() |
|
| 82 | except Exception as e: |
|
| 83 | logger.error("Error in step 1.3 of equipment_billing_output_category " + str(e)) |
|
| 84 | if cursor_energy_db: |
|
| 85 | cursor_energy_db.close() |
|
| 86 | if cnx_energy_db: |
|
| 87 | cnx_energy_db.close() |
|
| 88 | ||
| 89 | if cursor_system_db: |
|
| 90 | cursor_system_db.close() |
|
| 91 | if cnx_system_db: |
|
| 92 | cnx_system_db.close() |
|
| 93 | # sleep and continue the outermost while loop |
|
| 94 | time.sleep(60) |
|
| 95 | continue |
|
| 96 | ||
| 97 | print("Connected to MyEMS Energy Database") |
|
| 98 | ||
| 99 | cnx_billing_db = None |
|
| 100 | cursor_billing_db = None |
|
| 101 | try: |
|
| 102 | cnx_billing_db = mysql.connector.connect(**config.myems_billing_db) |
|
| 103 | cursor_billing_db = cnx_billing_db.cursor() |
|
| 104 | except Exception as e: |
|
| 105 | logger.error("Error in step 1.4 of equipment_billing_output_category " + str(e)) |
|
| 106 | if cursor_billing_db: |
|
| 107 | cursor_billing_db.close() |
|
| 108 | if cnx_billing_db: |
|
| 109 | cnx_billing_db.close() |
|
| 110 | ||
| 111 | if cursor_energy_db: |
|
| 112 | cursor_energy_db.close() |
|
| 113 | if cnx_energy_db: |
|
| 114 | cnx_energy_db.close() |
|
| 115 | ||
| 116 | if cursor_system_db: |
|
| 117 | cursor_system_db.close() |
|
| 118 | if cnx_system_db: |
|
| 119 | cnx_system_db.close() |
|
| 120 | # sleep and continue the outermost while loop |
|
| 121 | time.sleep(60) |
|
| 122 | continue |
|
| 123 | ||
| 124 | print("Connected to MyEMS Billing Database") |
|
| 125 | ||
| 126 | for equipment in equipment_list: |
|
| 127 | ||
| 128 | ############################################################################################################ |
|
| 129 | # Step 2: get the latest start_datetime_utc |
|
| 130 | ############################################################################################################ |
|
| 131 | print("Step 2: get the latest start_datetime_utc from billing database for " + equipment['name']) |
|
| 132 | try: |
|
| 133 | cursor_billing_db.execute(" SELECT MAX(start_datetime_utc) " |
|
| 134 | " FROM tbl_equipment_output_category_hourly " |
|
| 135 | " WHERE equipment_id = %s ", |
|
| 136 | (equipment['id'], )) |
|
| 137 | row_datetime = cursor_billing_db.fetchone() |
|
| 138 | start_datetime_utc = datetime.strptime(config.start_datetime_utc, '%Y-%m-%d %H:%M:%S') |
|
| 139 | start_datetime_utc = start_datetime_utc.replace(minute=0, second=0, microsecond=0, tzinfo=None) |
|
| 140 | ||
| 141 | if row_datetime is not None and len(row_datetime) > 0 and isinstance(row_datetime[0], datetime): |
|
| 142 | # replace second and microsecond with 0 |
|
| 143 | # note: do not replace minute in case of calculating in half hourly |
|
| 144 | start_datetime_utc = row_datetime[0].replace(second=0, microsecond=0, tzinfo=None) |
|
| 145 | # start from the next time slot |
|
| 146 | start_datetime_utc += timedelta(minutes=config.minutes_to_count) |
|
| 147 | ||
| 148 | print("start_datetime_utc: " + start_datetime_utc.isoformat()[0:19]) |
|
| 149 | except Exception as e: |
|
| 150 | logger.error("Error in step 2 of equipment_billing_output_category " + str(e)) |
|
| 151 | # break the for equipment loop |
|
| 152 | break |
|
| 153 | ||
| 154 | ############################################################################################################ |
|
| 155 | # Step 3: get all energy output data since the latest start_datetime_utc |
|
| 156 | ############################################################################################################ |
|
| 157 | print("Step 3: get all energy output data since the latest start_datetime_utc") |
|
| 158 | ||
| 159 | query = (" SELECT start_datetime_utc, energy_category_id, actual_value " |
|
| 160 | " FROM tbl_equipment_output_category_hourly " |
|
| 161 | " WHERE equipment_id = %s AND start_datetime_utc >= %s " |
|
| 162 | " ORDER BY id ") |
|
| 163 | cursor_energy_db.execute(query, (equipment['id'], start_datetime_utc, )) |
|
| 164 | rows_hourly = cursor_energy_db.fetchall() |
|
| 165 | ||
| 166 | if rows_hourly is None or len(rows_hourly) == 0: |
|
| 167 | print("Step 3: There isn't any energy output data to calculate. ") |
|
| 168 | # continue the for equipment loop |
|
| 169 | continue |
|
| 170 | ||
| 171 | energy_dict = dict() |
|
| 172 | energy_category_list = list() |
|
| 173 | end_datetime_utc = start_datetime_utc |
|
| 174 | for row_hourly in rows_hourly: |
|
| 175 | current_datetime_utc = row_hourly[0] |
|
| 176 | energy_category_id = row_hourly[1] |
|
| 177 | ||
| 178 | if energy_category_id not in energy_category_list: |
|
| 179 | energy_category_list.append(energy_category_id) |
|
| 180 | ||
| 181 | actual_value = row_hourly[2] |
|
| 182 | if energy_dict.get(current_datetime_utc) is None: |
|
| 183 | energy_dict[current_datetime_utc] = dict() |
|
| 184 | energy_dict[current_datetime_utc][energy_category_id] = actual_value |
|
| 185 | if current_datetime_utc > end_datetime_utc: |
|
| 186 | end_datetime_utc = current_datetime_utc |
|
| 187 | ||
| 188 | ############################################################################################################ |
|
| 189 | # Step 4: get tariffs |
|
| 190 | ############################################################################################################ |
|
| 191 | print("Step 4: get tariffs") |
|
| 192 | tariff_dict = dict() |
|
| 193 | for energy_category_id in energy_category_list: |
|
| 194 | tariff_dict[energy_category_id] = tariff.get_energy_category_tariffs(equipment['cost_center_id'], |
|
| 195 | energy_category_id, |
|
| 196 | start_datetime_utc, |
|
| 197 | end_datetime_utc) |
|
| 198 | ############################################################################################################ |
|
| 199 | # Step 5: calculate billing by multiplying energy with tariff |
|
| 200 | ############################################################################################################ |
|
| 201 | print("Step 5: calculate billing by multiplying energy with tariff") |
|
| 202 | billing_dict = dict() |
|
| 203 | ||
| 204 | if len(energy_dict) > 0: |
|
| 205 | for current_datetime_utc in energy_dict.keys(): |
|
| 206 | billing_dict[current_datetime_utc] = dict() |
|
| 207 | for energy_category_id in energy_category_list: |
|
| 208 | current_tariff = tariff_dict[energy_category_id].get(current_datetime_utc) |
|
| 209 | current_energy = energy_dict[current_datetime_utc].get(energy_category_id) |
|
| 210 | if current_tariff is not None \ |
|
| 211 | and isinstance(current_tariff, Decimal) \ |
|
| 212 | and current_energy is not None \ |
|
| 213 | and isinstance(current_energy, Decimal): |
|
| 214 | billing_dict[current_datetime_utc][energy_category_id] = \ |
|
| 215 | current_energy * current_tariff |
|
| 216 | ||
| 217 | if len(billing_dict[current_datetime_utc]) == 0: |
|
| 218 | del billing_dict[current_datetime_utc] |
|
| 219 | ||
| 220 | ############################################################################################################ |
|
| 221 | # Step 6: save billing data to billing database |
|
| 222 | ############################################################################################################ |
|
| 223 | print("Step 6: save billing data to billing database") |
|
| 224 | ||
| 225 | if len(billing_dict) > 0: |
|
| 226 | try: |
|
| 227 | add_values = (" INSERT INTO tbl_equipment_output_category_hourly " |
|
| 228 | " (equipment_id, " |
|
| 229 | " energy_category_id, " |
|
| 230 | " start_datetime_utc, " |
|
| 231 | " actual_value) " |
|
| 232 | " VALUES ") |
|
| 233 | ||
| 234 | for current_datetime_utc in billing_dict: |
|
| 235 | for energy_category_id in energy_category_list: |
|
| 236 | current_billing = billing_dict[current_datetime_utc].get(energy_category_id) |
|
| 237 | if current_billing is not None and isinstance(current_billing, Decimal): |
|
| 238 | add_values += " (" + str(equipment['id']) + "," |
|
| 239 | add_values += " " + str(energy_category_id) + "," |
|
| 240 | add_values += "'" + current_datetime_utc.isoformat()[0:19] + "'," |
|
| 241 | add_values += str(billing_dict[current_datetime_utc][energy_category_id]) + "), " |
|
| 242 | print("add_values:" + add_values) |
|
| 243 | # trim ", " at the end of string and then execute |
|
| 244 | cursor_billing_db.execute(add_values[:-2]) |
|
| 245 | cnx_billing_db.commit() |
|
| 246 | except Exception as e: |
|
| 247 | logger.error("Error in step 6 of equipment_billing_output_category " + str(e)) |
|
| 248 | # break the for equipment loop |
|
| 249 | break |
|
| 250 | ||
| 251 | # end of for equipment loop |
|
| 252 | if cnx_system_db: |
|
| 253 | cnx_system_db.close() |
|
| 254 | if cursor_system_db: |
|
| 255 | cursor_system_db.close() |
|
| 256 | ||
| 257 | if cnx_energy_db: |
|
| 258 | cnx_energy_db.close() |
|
| 259 | if cursor_energy_db: |
|
| 260 | cursor_energy_db.close() |
|
| 261 | ||
| 262 | if cnx_billing_db: |
|
| 263 | cnx_billing_db.close() |
|
| 264 | if cursor_billing_db: |
|
| 265 | cursor_billing_db.close() |
|
| 266 | print("go to sleep 300 seconds...") |
|
| 267 | time.sleep(300) |
|
| 268 | print("wake from sleep, and continue to work...") |
|
| 269 | # end of the outermost while loop |
|
| 270 | ||
| @@ 21-268 (lines=248) @@ | ||
| 18 | ######################################################################################################################## |
|
| 19 | ||
| 20 | ||
| 21 | def main(logger): |
|
| 22 | ||
| 23 | while True: |
|
| 24 | # the outermost while loop |
|
| 25 | ################################################################################################################ |
|
| 26 | # Step 1: get all shopfloors |
|
| 27 | ################################################################################################################ |
|
| 28 | cnx_system_db = None |
|
| 29 | cursor_system_db = None |
|
| 30 | try: |
|
| 31 | cnx_system_db = mysql.connector.connect(**config.myems_system_db) |
|
| 32 | cursor_system_db = cnx_system_db.cursor() |
|
| 33 | except Exception as e: |
|
| 34 | logger.error("Error in step 1.1 of shopfloor_billing_input_item " + str(e)) |
|
| 35 | if cursor_system_db: |
|
| 36 | cursor_system_db.close() |
|
| 37 | if cnx_system_db: |
|
| 38 | cnx_system_db.close() |
|
| 39 | # sleep and continue the outermost while loop |
|
| 40 | time.sleep(60) |
|
| 41 | continue |
|
| 42 | ||
| 43 | print("Connected to MyEMS System Database") |
|
| 44 | ||
| 45 | try: |
|
| 46 | cursor_system_db.execute(" SELECT id, name, cost_center_id " |
|
| 47 | " FROM tbl_shopfloors " |
|
| 48 | " ORDER BY id ") |
|
| 49 | rows_shopfloors = cursor_system_db.fetchall() |
|
| 50 | ||
| 51 | if rows_shopfloors is None or len(rows_shopfloors) == 0: |
|
| 52 | print("Step 1.2: There isn't any shopfloors. ") |
|
| 53 | if cursor_system_db: |
|
| 54 | cursor_system_db.close() |
|
| 55 | if cnx_system_db: |
|
| 56 | cnx_system_db.close() |
|
| 57 | # sleep and continue the outermost while loop |
|
| 58 | time.sleep(60) |
|
| 59 | continue |
|
| 60 | ||
| 61 | shopfloor_list = list() |
|
| 62 | for row in rows_shopfloors: |
|
| 63 | shopfloor_list.append({"id": row[0], "name": row[1], "cost_center_id": row[2]}) |
|
| 64 | ||
| 65 | except Exception as e: |
|
| 66 | logger.error("Error in step 1.2 of shopfloor_billing_input_item " + str(e)) |
|
| 67 | if cursor_system_db: |
|
| 68 | cursor_system_db.close() |
|
| 69 | if cnx_system_db: |
|
| 70 | cnx_system_db.close() |
|
| 71 | # sleep and continue the outermost while loop |
|
| 72 | time.sleep(60) |
|
| 73 | continue |
|
| 74 | ||
| 75 | print("Step 1.2: Got all shopfloors from MyEMS System Database") |
|
| 76 | ||
| 77 | cnx_energy_db = None |
|
| 78 | cursor_energy_db = None |
|
| 79 | try: |
|
| 80 | cnx_energy_db = mysql.connector.connect(**config.myems_energy_db) |
|
| 81 | cursor_energy_db = cnx_energy_db.cursor() |
|
| 82 | except Exception as e: |
|
| 83 | logger.error("Error in step 1.3 of shopfloor_billing_input_item " + str(e)) |
|
| 84 | if cursor_energy_db: |
|
| 85 | cursor_energy_db.close() |
|
| 86 | if cnx_energy_db: |
|
| 87 | cnx_energy_db.close() |
|
| 88 | ||
| 89 | if cursor_system_db: |
|
| 90 | cursor_system_db.close() |
|
| 91 | if cnx_system_db: |
|
| 92 | cnx_system_db.close() |
|
| 93 | # sleep and continue the outermost while loop |
|
| 94 | time.sleep(60) |
|
| 95 | continue |
|
| 96 | ||
| 97 | print("Connected to MyEMS Energy Database") |
|
| 98 | ||
| 99 | cnx_billing_db = None |
|
| 100 | cursor_billing_db = None |
|
| 101 | try: |
|
| 102 | cnx_billing_db = mysql.connector.connect(**config.myems_billing_db) |
|
| 103 | cursor_billing_db = cnx_billing_db.cursor() |
|
| 104 | except Exception as e: |
|
| 105 | logger.error("Error in step 1.4 of shopfloor_billing_input_item " + str(e)) |
|
| 106 | if cursor_billing_db: |
|
| 107 | cursor_billing_db.close() |
|
| 108 | if cnx_billing_db: |
|
| 109 | cnx_billing_db.close() |
|
| 110 | ||
| 111 | if cursor_energy_db: |
|
| 112 | cursor_energy_db.close() |
|
| 113 | if cnx_energy_db: |
|
| 114 | cnx_energy_db.close() |
|
| 115 | ||
| 116 | if cursor_system_db: |
|
| 117 | cursor_system_db.close() |
|
| 118 | if cnx_system_db: |
|
| 119 | cnx_system_db.close() |
|
| 120 | # sleep and continue the outermost while loop |
|
| 121 | time.sleep(60) |
|
| 122 | continue |
|
| 123 | ||
| 124 | print("Connected to MyEMS Billing Database") |
|
| 125 | ||
| 126 | for shopfloor in shopfloor_list: |
|
| 127 | ||
| 128 | ############################################################################################################ |
|
| 129 | # Step 2: get the latest start_datetime_utc |
|
| 130 | ############################################################################################################ |
|
| 131 | print("Step 2: get the latest start_datetime_utc from billing database for " + shopfloor['name']) |
|
| 132 | try: |
|
| 133 | cursor_billing_db.execute(" SELECT MAX(start_datetime_utc) " |
|
| 134 | " FROM tbl_shopfloor_input_item_hourly " |
|
| 135 | " WHERE shopfloor_id = %s ", |
|
| 136 | (shopfloor['id'], )) |
|
| 137 | row_datetime = cursor_billing_db.fetchone() |
|
| 138 | start_datetime_utc = datetime.strptime(config.start_datetime_utc, '%Y-%m-%d %H:%M:%S') |
|
| 139 | start_datetime_utc = start_datetime_utc.replace(minute=0, second=0, microsecond=0, tzinfo=None) |
|
| 140 | ||
| 141 | if row_datetime is not None and len(row_datetime) > 0 and isinstance(row_datetime[0], datetime): |
|
| 142 | # replace second and microsecond with 0 |
|
| 143 | # note: do not replace minute in case of calculating in half hourly |
|
| 144 | start_datetime_utc = row_datetime[0].replace(second=0, microsecond=0, tzinfo=None) |
|
| 145 | # start from the next time slot |
|
| 146 | start_datetime_utc += timedelta(minutes=config.minutes_to_count) |
|
| 147 | ||
| 148 | print("start_datetime_utc: " + start_datetime_utc.isoformat()[0:19]) |
|
| 149 | except Exception as e: |
|
| 150 | logger.error("Error in step 2 of shopfloor_billing_input_item " + str(e)) |
|
| 151 | # break the for shopfloor loop |
|
| 152 | break |
|
| 153 | ||
| 154 | ############################################################################################################ |
|
| 155 | # Step 3: get all energy input data since the latest start_datetime_utc |
|
| 156 | ############################################################################################################ |
|
| 157 | print("Step 3: get all energy input data since the latest start_datetime_utc") |
|
| 158 | ||
| 159 | query = (" SELECT start_datetime_utc, energy_item_id, actual_value " |
|
| 160 | " FROM tbl_shopfloor_input_item_hourly " |
|
| 161 | " WHERE shopfloor_id = %s AND start_datetime_utc >= %s " |
|
| 162 | " ORDER BY id ") |
|
| 163 | cursor_energy_db.execute(query, (shopfloor['id'], start_datetime_utc, )) |
|
| 164 | rows_hourly = cursor_energy_db.fetchall() |
|
| 165 | ||
| 166 | if rows_hourly is None or len(rows_hourly) == 0: |
|
| 167 | print("Step 3: There isn't any energy input data to calculate. ") |
|
| 168 | # continue the for shopfloor loop |
|
| 169 | continue |
|
| 170 | ||
| 171 | energy_dict = dict() |
|
| 172 | energy_item_list = list() |
|
| 173 | end_datetime_utc = start_datetime_utc |
|
| 174 | for row_hourly in rows_hourly: |
|
| 175 | current_datetime_utc = row_hourly[0] |
|
| 176 | energy_item_id = row_hourly[1] |
|
| 177 | ||
| 178 | if energy_item_id not in energy_item_list: |
|
| 179 | energy_item_list.append(energy_item_id) |
|
| 180 | ||
| 181 | actual_value = row_hourly[2] |
|
| 182 | if energy_dict.get(current_datetime_utc) is None: |
|
| 183 | energy_dict[current_datetime_utc] = dict() |
|
| 184 | energy_dict[current_datetime_utc][energy_item_id] = actual_value |
|
| 185 | if current_datetime_utc > end_datetime_utc: |
|
| 186 | end_datetime_utc = current_datetime_utc |
|
| 187 | ||
| 188 | ############################################################################################################ |
|
| 189 | # Step 4: get tariffs |
|
| 190 | ############################################################################################################ |
|
| 191 | print("Step 4: get tariffs") |
|
| 192 | tariff_dict = dict() |
|
| 193 | for energy_item_id in energy_item_list: |
|
| 194 | tariff_dict[energy_item_id] = tariff.get_energy_item_tariffs(shopfloor['cost_center_id'], |
|
| 195 | energy_item_id, |
|
| 196 | start_datetime_utc, |
|
| 197 | end_datetime_utc) |
|
| 198 | ############################################################################################################ |
|
| 199 | # Step 5: calculate billing by multiplying energy with tariff |
|
| 200 | ############################################################################################################ |
|
| 201 | print("Step 5: calculate billing by multiplying energy with tariff") |
|
| 202 | billing_dict = dict() |
|
| 203 | ||
| 204 | if len(energy_dict) > 0: |
|
| 205 | for current_datetime_utc in energy_dict.keys(): |
|
| 206 | billing_dict[current_datetime_utc] = dict() |
|
| 207 | for energy_item_id in energy_item_list: |
|
| 208 | current_tariff = tariff_dict[energy_item_id].get(current_datetime_utc) |
|
| 209 | current_energy = energy_dict[current_datetime_utc].get(energy_item_id) |
|
| 210 | if current_tariff is not None \ |
|
| 211 | and isinstance(current_tariff, Decimal) \ |
|
| 212 | and current_energy is not None \ |
|
| 213 | and isinstance(current_energy, Decimal): |
|
| 214 | billing_dict[current_datetime_utc][energy_item_id] = \ |
|
| 215 | current_energy * current_tariff |
|
| 216 | ||
| 217 | if len(billing_dict[current_datetime_utc]) == 0: |
|
| 218 | del billing_dict[current_datetime_utc] |
|
| 219 | ||
| 220 | ############################################################################################################ |
|
| 221 | # Step 6: save billing data to billing database |
|
| 222 | ############################################################################################################ |
|
| 223 | print("Step 6: save billing data to billing database") |
|
| 224 | ||
| 225 | if len(billing_dict) > 0: |
|
| 226 | try: |
|
| 227 | add_values = (" INSERT INTO tbl_shopfloor_input_item_hourly " |
|
| 228 | " (shopfloor_id, " |
|
| 229 | " energy_item_id, " |
|
| 230 | " start_datetime_utc, " |
|
| 231 | " actual_value) " |
|
| 232 | " VALUES ") |
|
| 233 | ||
| 234 | for current_datetime_utc in billing_dict: |
|
| 235 | for energy_item_id in energy_item_list: |
|
| 236 | current_billing = billing_dict[current_datetime_utc].get(energy_item_id) |
|
| 237 | if current_billing is not None and isinstance(current_billing, Decimal): |
|
| 238 | add_values += " (" + str(shopfloor['id']) + "," |
|
| 239 | add_values += " " + str(energy_item_id) + "," |
|
| 240 | add_values += "'" + current_datetime_utc.isoformat()[0:19] + "'," |
|
| 241 | add_values += str(billing_dict[current_datetime_utc][energy_item_id]) + "), " |
|
| 242 | print("add_values:" + add_values) |
|
| 243 | # trim ", " at the end of string and then execute |
|
| 244 | cursor_billing_db.execute(add_values[:-2]) |
|
| 245 | cnx_billing_db.commit() |
|
| 246 | except Exception as e: |
|
| 247 | logger.error("Error in step 6 of shopfloor_billing_input_item " + str(e)) |
|
| 248 | # break the for shopfloor loop |
|
| 249 | break |
|
| 250 | ||
| 251 | # end of for shopfloor loop |
|
| 252 | if cnx_system_db: |
|
| 253 | cnx_system_db.close() |
|
| 254 | if cursor_system_db: |
|
| 255 | cursor_system_db.close() |
|
| 256 | ||
| 257 | if cnx_energy_db: |
|
| 258 | cnx_energy_db.close() |
|
| 259 | if cursor_energy_db: |
|
| 260 | cursor_energy_db.close() |
|
| 261 | ||
| 262 | if cnx_billing_db: |
|
| 263 | cnx_billing_db.close() |
|
| 264 | if cursor_billing_db: |
|
| 265 | cursor_billing_db.close() |
|
| 266 | print("go to sleep 300 seconds...") |
|
| 267 | time.sleep(300) |
|
| 268 | print("wake from sleep, and continue to work...") |
|
| 269 | # end of the outermost while loop |
|
| 270 | ||
| @@ 21-268 (lines=248) @@ | ||
| 18 | ######################################################################################################################## |
|
| 19 | ||
| 20 | ||
| 21 | def main(logger): |
|
| 22 | ||
| 23 | while True: |
|
| 24 | # the outermost while loop |
|
| 25 | ################################################################################################################ |
|
| 26 | # Step 1: get all stores |
|
| 27 | ################################################################################################################ |
|
| 28 | cnx_system_db = None |
|
| 29 | cursor_system_db = None |
|
| 30 | try: |
|
| 31 | cnx_system_db = mysql.connector.connect(**config.myems_system_db) |
|
| 32 | cursor_system_db = cnx_system_db.cursor() |
|
| 33 | except Exception as e: |
|
| 34 | logger.error("Error in step 1.1 of store_billing_input_category " + str(e)) |
|
| 35 | if cursor_system_db: |
|
| 36 | cursor_system_db.close() |
|
| 37 | if cnx_system_db: |
|
| 38 | cnx_system_db.close() |
|
| 39 | # sleep and continue the outermost while loop |
|
| 40 | time.sleep(60) |
|
| 41 | continue |
|
| 42 | ||
| 43 | print("Connected to MyEMS System Database") |
|
| 44 | ||
| 45 | try: |
|
| 46 | cursor_system_db.execute(" SELECT id, name, cost_center_id " |
|
| 47 | " FROM tbl_stores " |
|
| 48 | " ORDER BY id ") |
|
| 49 | rows_stores = cursor_system_db.fetchall() |
|
| 50 | ||
| 51 | if rows_stores is None or len(rows_stores) == 0: |
|
| 52 | print("Step 1.2: There isn't any stores. ") |
|
| 53 | if cursor_system_db: |
|
| 54 | cursor_system_db.close() |
|
| 55 | if cnx_system_db: |
|
| 56 | cnx_system_db.close() |
|
| 57 | # sleep and continue the outermost while loop |
|
| 58 | time.sleep(60) |
|
| 59 | continue |
|
| 60 | ||
| 61 | store_list = list() |
|
| 62 | for row in rows_stores: |
|
| 63 | store_list.append({"id": row[0], "name": row[1], "cost_center_id": row[2]}) |
|
| 64 | ||
| 65 | except Exception as e: |
|
| 66 | logger.error("Error in step 1.2 of store_billing_input_category " + str(e)) |
|
| 67 | if cursor_system_db: |
|
| 68 | cursor_system_db.close() |
|
| 69 | if cnx_system_db: |
|
| 70 | cnx_system_db.close() |
|
| 71 | # sleep and continue the outermost while loop |
|
| 72 | time.sleep(60) |
|
| 73 | continue |
|
| 74 | ||
| 75 | print("Step 1.2: Got all stores from MyEMS System Database") |
|
| 76 | ||
| 77 | cnx_energy_db = None |
|
| 78 | cursor_energy_db = None |
|
| 79 | try: |
|
| 80 | cnx_energy_db = mysql.connector.connect(**config.myems_energy_db) |
|
| 81 | cursor_energy_db = cnx_energy_db.cursor() |
|
| 82 | except Exception as e: |
|
| 83 | logger.error("Error in step 1.3 of store_billing_input_category " + str(e)) |
|
| 84 | if cursor_energy_db: |
|
| 85 | cursor_energy_db.close() |
|
| 86 | if cnx_energy_db: |
|
| 87 | cnx_energy_db.close() |
|
| 88 | ||
| 89 | if cursor_system_db: |
|
| 90 | cursor_system_db.close() |
|
| 91 | if cnx_system_db: |
|
| 92 | cnx_system_db.close() |
|
| 93 | # sleep and continue the outermost while loop |
|
| 94 | time.sleep(60) |
|
| 95 | continue |
|
| 96 | ||
| 97 | print("Connected to MyEMS Energy Database") |
|
| 98 | ||
| 99 | cnx_billing_db = None |
|
| 100 | cursor_billing_db = None |
|
| 101 | try: |
|
| 102 | cnx_billing_db = mysql.connector.connect(**config.myems_billing_db) |
|
| 103 | cursor_billing_db = cnx_billing_db.cursor() |
|
| 104 | except Exception as e: |
|
| 105 | logger.error("Error in step 1.4 of store_billing_input_category " + str(e)) |
|
| 106 | if cursor_billing_db: |
|
| 107 | cursor_billing_db.close() |
|
| 108 | if cnx_billing_db: |
|
| 109 | cnx_billing_db.close() |
|
| 110 | ||
| 111 | if cursor_energy_db: |
|
| 112 | cursor_energy_db.close() |
|
| 113 | if cnx_energy_db: |
|
| 114 | cnx_energy_db.close() |
|
| 115 | ||
| 116 | if cursor_system_db: |
|
| 117 | cursor_system_db.close() |
|
| 118 | if cnx_system_db: |
|
| 119 | cnx_system_db.close() |
|
| 120 | # sleep and continue the outermost while loop |
|
| 121 | time.sleep(60) |
|
| 122 | continue |
|
| 123 | ||
| 124 | print("Connected to MyEMS Billing Database") |
|
| 125 | ||
| 126 | for store in store_list: |
|
| 127 | ||
| 128 | ############################################################################################################ |
|
| 129 | # Step 2: get the latest start_datetime_utc |
|
| 130 | ############################################################################################################ |
|
| 131 | print("Step 2: get the latest start_datetime_utc from billing database for " + store['name']) |
|
| 132 | try: |
|
| 133 | cursor_billing_db.execute(" SELECT MAX(start_datetime_utc) " |
|
| 134 | " FROM tbl_store_input_category_hourly " |
|
| 135 | " WHERE store_id = %s ", |
|
| 136 | (store['id'], )) |
|
| 137 | row_datetime = cursor_billing_db.fetchone() |
|
| 138 | start_datetime_utc = datetime.strptime(config.start_datetime_utc, '%Y-%m-%d %H:%M:%S') |
|
| 139 | start_datetime_utc = start_datetime_utc.replace(minute=0, second=0, microsecond=0, tzinfo=None) |
|
| 140 | ||
| 141 | if row_datetime is not None and len(row_datetime) > 0 and isinstance(row_datetime[0], datetime): |
|
| 142 | # replace second and microsecond with 0 |
|
| 143 | # note: do not replace minute in case of calculating in half hourly |
|
| 144 | start_datetime_utc = row_datetime[0].replace(second=0, microsecond=0, tzinfo=None) |
|
| 145 | # start from the next time slot |
|
| 146 | start_datetime_utc += timedelta(minutes=config.minutes_to_count) |
|
| 147 | ||
| 148 | print("start_datetime_utc: " + start_datetime_utc.isoformat()[0:19]) |
|
| 149 | except Exception as e: |
|
| 150 | logger.error("Error in step 2 of store_billing_input_category " + str(e)) |
|
| 151 | # break the for store loop |
|
| 152 | break |
|
| 153 | ||
| 154 | ############################################################################################################ |
|
| 155 | # Step 3: get all energy input data since the latest start_datetime_utc |
|
| 156 | ############################################################################################################ |
|
| 157 | print("Step 3: get all energy input data since the latest start_datetime_utc") |
|
| 158 | ||
| 159 | query = (" SELECT start_datetime_utc, energy_category_id, actual_value " |
|
| 160 | " FROM tbl_store_input_category_hourly " |
|
| 161 | " WHERE store_id = %s AND start_datetime_utc >= %s " |
|
| 162 | " ORDER BY id ") |
|
| 163 | cursor_energy_db.execute(query, (store['id'], start_datetime_utc, )) |
|
| 164 | rows_hourly = cursor_energy_db.fetchall() |
|
| 165 | ||
| 166 | if rows_hourly is None or len(rows_hourly) == 0: |
|
| 167 | print("Step 3: There isn't any energy input data to calculate. ") |
|
| 168 | # continue the for store loop |
|
| 169 | continue |
|
| 170 | ||
| 171 | energy_dict = dict() |
|
| 172 | energy_category_list = list() |
|
| 173 | end_datetime_utc = start_datetime_utc |
|
| 174 | for row_hourly in rows_hourly: |
|
| 175 | current_datetime_utc = row_hourly[0] |
|
| 176 | energy_category_id = row_hourly[1] |
|
| 177 | ||
| 178 | if energy_category_id not in energy_category_list: |
|
| 179 | energy_category_list.append(energy_category_id) |
|
| 180 | ||
| 181 | actual_value = row_hourly[2] |
|
| 182 | if energy_dict.get(current_datetime_utc) is None: |
|
| 183 | energy_dict[current_datetime_utc] = dict() |
|
| 184 | energy_dict[current_datetime_utc][energy_category_id] = actual_value |
|
| 185 | if current_datetime_utc > end_datetime_utc: |
|
| 186 | end_datetime_utc = current_datetime_utc |
|
| 187 | ||
| 188 | ############################################################################################################ |
|
| 189 | # Step 4: get tariffs |
|
| 190 | ############################################################################################################ |
|
| 191 | print("Step 4: get tariffs") |
|
| 192 | tariff_dict = dict() |
|
| 193 | for energy_category_id in energy_category_list: |
|
| 194 | tariff_dict[energy_category_id] = tariff.get_energy_category_tariffs(store['cost_center_id'], |
|
| 195 | energy_category_id, |
|
| 196 | start_datetime_utc, |
|
| 197 | end_datetime_utc) |
|
| 198 | ############################################################################################################ |
|
| 199 | # Step 5: calculate billing by multiplying energy with tariff |
|
| 200 | ############################################################################################################ |
|
| 201 | print("Step 5: calculate billing by multiplying energy with tariff") |
|
| 202 | billing_dict = dict() |
|
| 203 | ||
| 204 | if len(energy_dict) > 0: |
|
| 205 | for current_datetime_utc in energy_dict.keys(): |
|
| 206 | billing_dict[current_datetime_utc] = dict() |
|
| 207 | for energy_category_id in energy_category_list: |
|
| 208 | current_tariff = tariff_dict[energy_category_id].get(current_datetime_utc) |
|
| 209 | current_energy = energy_dict[current_datetime_utc].get(energy_category_id) |
|
| 210 | if current_tariff is not None \ |
|
| 211 | and isinstance(current_tariff, Decimal) \ |
|
| 212 | and current_energy is not None \ |
|
| 213 | and isinstance(current_energy, Decimal): |
|
| 214 | billing_dict[current_datetime_utc][energy_category_id] = \ |
|
| 215 | current_energy * current_tariff |
|
| 216 | ||
| 217 | if len(billing_dict[current_datetime_utc]) == 0: |
|
| 218 | del billing_dict[current_datetime_utc] |
|
| 219 | ||
| 220 | ############################################################################################################ |
|
| 221 | # Step 6: save billing data to billing database |
|
| 222 | ############################################################################################################ |
|
| 223 | print("Step 6: save billing data to billing database") |
|
| 224 | ||
| 225 | if len(billing_dict) > 0: |
|
| 226 | try: |
|
| 227 | add_values = (" INSERT INTO tbl_store_input_category_hourly " |
|
| 228 | " (store_id, " |
|
| 229 | " energy_category_id, " |
|
| 230 | " start_datetime_utc, " |
|
| 231 | " actual_value) " |
|
| 232 | " VALUES ") |
|
| 233 | ||
| 234 | for current_datetime_utc in billing_dict: |
|
| 235 | for energy_category_id in energy_category_list: |
|
| 236 | current_billing = billing_dict[current_datetime_utc].get(energy_category_id) |
|
| 237 | if current_billing is not None and isinstance(current_billing, Decimal): |
|
| 238 | add_values += " (" + str(store['id']) + "," |
|
| 239 | add_values += " " + str(energy_category_id) + "," |
|
| 240 | add_values += "'" + current_datetime_utc.isoformat()[0:19] + "'," |
|
| 241 | add_values += str(billing_dict[current_datetime_utc][energy_category_id]) + "), " |
|
| 242 | print("add_values:" + add_values) |
|
| 243 | # trim ", " at the end of string and then execute |
|
| 244 | cursor_billing_db.execute(add_values[:-2]) |
|
| 245 | cnx_billing_db.commit() |
|
| 246 | except Exception as e: |
|
| 247 | logger.error("Error in step 6 of store_billing_input_category " + str(e)) |
|
| 248 | # break the for store loop |
|
| 249 | break |
|
| 250 | ||
| 251 | # end of for store loop |
|
| 252 | if cnx_system_db: |
|
| 253 | cnx_system_db.close() |
|
| 254 | if cursor_system_db: |
|
| 255 | cursor_system_db.close() |
|
| 256 | ||
| 257 | if cnx_energy_db: |
|
| 258 | cnx_energy_db.close() |
|
| 259 | if cursor_energy_db: |
|
| 260 | cursor_energy_db.close() |
|
| 261 | ||
| 262 | if cnx_billing_db: |
|
| 263 | cnx_billing_db.close() |
|
| 264 | if cursor_billing_db: |
|
| 265 | cursor_billing_db.close() |
|
| 266 | print("go to sleep 300 seconds...") |
|
| 267 | time.sleep(300) |
|
| 268 | print("wake from sleep, and continue to work...") |
|
| 269 | # end of the outermost while loop |
|
| 270 | ||
| @@ 21-268 (lines=248) @@ | ||
| 18 | ######################################################################################################################## |
|
| 19 | ||
| 20 | ||
| 21 | def main(logger): |
|
| 22 | ||
| 23 | while True: |
|
| 24 | # the outermost while loop |
|
| 25 | ################################################################################################################ |
|
| 26 | # Step 1: get all stores |
|
| 27 | ################################################################################################################ |
|
| 28 | cnx_system_db = None |
|
| 29 | cursor_system_db = None |
|
| 30 | try: |
|
| 31 | cnx_system_db = mysql.connector.connect(**config.myems_system_db) |
|
| 32 | cursor_system_db = cnx_system_db.cursor() |
|
| 33 | except Exception as e: |
|
| 34 | logger.error("Error in step 1.1 of store_billing_input_item " + str(e)) |
|
| 35 | if cursor_system_db: |
|
| 36 | cursor_system_db.close() |
|
| 37 | if cnx_system_db: |
|
| 38 | cnx_system_db.close() |
|
| 39 | # sleep and continue the outermost while loop |
|
| 40 | time.sleep(60) |
|
| 41 | continue |
|
| 42 | ||
| 43 | print("Connected to MyEMS System Database") |
|
| 44 | ||
| 45 | try: |
|
| 46 | cursor_system_db.execute(" SELECT id, name, cost_center_id " |
|
| 47 | " FROM tbl_stores " |
|
| 48 | " ORDER BY id ") |
|
| 49 | rows_stores = cursor_system_db.fetchall() |
|
| 50 | ||
| 51 | if rows_stores is None or len(rows_stores) == 0: |
|
| 52 | print("Step 1.2: There isn't any stores. ") |
|
| 53 | if cursor_system_db: |
|
| 54 | cursor_system_db.close() |
|
| 55 | if cnx_system_db: |
|
| 56 | cnx_system_db.close() |
|
| 57 | # sleep and continue the outermost while loop |
|
| 58 | time.sleep(60) |
|
| 59 | continue |
|
| 60 | ||
| 61 | store_list = list() |
|
| 62 | for row in rows_stores: |
|
| 63 | store_list.append({"id": row[0], "name": row[1], "cost_center_id": row[2]}) |
|
| 64 | ||
| 65 | except Exception as e: |
|
| 66 | logger.error("Error in step 1.2 of store_billing_input_item " + str(e)) |
|
| 67 | if cursor_system_db: |
|
| 68 | cursor_system_db.close() |
|
| 69 | if cnx_system_db: |
|
| 70 | cnx_system_db.close() |
|
| 71 | # sleep and continue the outermost while loop |
|
| 72 | time.sleep(60) |
|
| 73 | continue |
|
| 74 | ||
| 75 | print("Step 1.2: Got all stores from MyEMS System Database") |
|
| 76 | ||
| 77 | cnx_energy_db = None |
|
| 78 | cursor_energy_db = None |
|
| 79 | try: |
|
| 80 | cnx_energy_db = mysql.connector.connect(**config.myems_energy_db) |
|
| 81 | cursor_energy_db = cnx_energy_db.cursor() |
|
| 82 | except Exception as e: |
|
| 83 | logger.error("Error in step 1.3 of store_billing_input_item " + str(e)) |
|
| 84 | if cursor_energy_db: |
|
| 85 | cursor_energy_db.close() |
|
| 86 | if cnx_energy_db: |
|
| 87 | cnx_energy_db.close() |
|
| 88 | ||
| 89 | if cursor_system_db: |
|
| 90 | cursor_system_db.close() |
|
| 91 | if cnx_system_db: |
|
| 92 | cnx_system_db.close() |
|
| 93 | # sleep and continue the outermost while loop |
|
| 94 | time.sleep(60) |
|
| 95 | continue |
|
| 96 | ||
| 97 | print("Connected to MyEMS Energy Database") |
|
| 98 | ||
| 99 | cnx_billing_db = None |
|
| 100 | cursor_billing_db = None |
|
| 101 | try: |
|
| 102 | cnx_billing_db = mysql.connector.connect(**config.myems_billing_db) |
|
| 103 | cursor_billing_db = cnx_billing_db.cursor() |
|
| 104 | except Exception as e: |
|
| 105 | logger.error("Error in step 1.4 of store_billing_input_item " + str(e)) |
|
| 106 | if cursor_billing_db: |
|
| 107 | cursor_billing_db.close() |
|
| 108 | if cnx_billing_db: |
|
| 109 | cnx_billing_db.close() |
|
| 110 | ||
| 111 | if cursor_energy_db: |
|
| 112 | cursor_energy_db.close() |
|
| 113 | if cnx_energy_db: |
|
| 114 | cnx_energy_db.close() |
|
| 115 | ||
| 116 | if cursor_system_db: |
|
| 117 | cursor_system_db.close() |
|
| 118 | if cnx_system_db: |
|
| 119 | cnx_system_db.close() |
|
| 120 | # sleep and continue the outermost while loop |
|
| 121 | time.sleep(60) |
|
| 122 | continue |
|
| 123 | ||
| 124 | print("Connected to MyEMS Billing Database") |
|
| 125 | ||
| 126 | for store in store_list: |
|
| 127 | ||
| 128 | ############################################################################################################ |
|
| 129 | # Step 2: get the latest start_datetime_utc |
|
| 130 | ############################################################################################################ |
|
| 131 | print("Step 2: get the latest start_datetime_utc from billing database for " + store['name']) |
|
| 132 | try: |
|
| 133 | cursor_billing_db.execute(" SELECT MAX(start_datetime_utc) " |
|
| 134 | " FROM tbl_store_input_item_hourly " |
|
| 135 | " WHERE store_id = %s ", |
|
| 136 | (store['id'], )) |
|
| 137 | row_datetime = cursor_billing_db.fetchone() |
|
| 138 | start_datetime_utc = datetime.strptime(config.start_datetime_utc, '%Y-%m-%d %H:%M:%S') |
|
| 139 | start_datetime_utc = start_datetime_utc.replace(minute=0, second=0, microsecond=0, tzinfo=None) |
|
| 140 | ||
| 141 | if row_datetime is not None and len(row_datetime) > 0 and isinstance(row_datetime[0], datetime): |
|
| 142 | # replace second and microsecond with 0 |
|
| 143 | # note: do not replace minute in case of calculating in half hourly |
|
| 144 | start_datetime_utc = row_datetime[0].replace(second=0, microsecond=0, tzinfo=None) |
|
| 145 | # start from the next time slot |
|
| 146 | start_datetime_utc += timedelta(minutes=config.minutes_to_count) |
|
| 147 | ||
| 148 | print("start_datetime_utc: " + start_datetime_utc.isoformat()[0:19]) |
|
| 149 | except Exception as e: |
|
| 150 | logger.error("Error in step 2 of store_billing_input_item " + str(e)) |
|
| 151 | # break the for store loop |
|
| 152 | break |
|
| 153 | ||
| 154 | ############################################################################################################ |
|
| 155 | # Step 3: get all energy input data since the latest start_datetime_utc |
|
| 156 | ############################################################################################################ |
|
| 157 | print("Step 3: get all energy input data since the latest start_datetime_utc") |
|
| 158 | ||
| 159 | query = (" SELECT start_datetime_utc, energy_item_id, actual_value " |
|
| 160 | " FROM tbl_store_input_item_hourly " |
|
| 161 | " WHERE store_id = %s AND start_datetime_utc >= %s " |
|
| 162 | " ORDER BY id ") |
|
| 163 | cursor_energy_db.execute(query, (store['id'], start_datetime_utc, )) |
|
| 164 | rows_hourly = cursor_energy_db.fetchall() |
|
| 165 | ||
| 166 | if rows_hourly is None or len(rows_hourly) == 0: |
|
| 167 | print("Step 3: There isn't any energy input data to calculate. ") |
|
| 168 | # continue the for store loop |
|
| 169 | continue |
|
| 170 | ||
| 171 | energy_dict = dict() |
|
| 172 | energy_item_list = list() |
|
| 173 | end_datetime_utc = start_datetime_utc |
|
| 174 | for row_hourly in rows_hourly: |
|
| 175 | current_datetime_utc = row_hourly[0] |
|
| 176 | energy_item_id = row_hourly[1] |
|
| 177 | ||
| 178 | if energy_item_id not in energy_item_list: |
|
| 179 | energy_item_list.append(energy_item_id) |
|
| 180 | ||
| 181 | actual_value = row_hourly[2] |
|
| 182 | if energy_dict.get(current_datetime_utc) is None: |
|
| 183 | energy_dict[current_datetime_utc] = dict() |
|
| 184 | energy_dict[current_datetime_utc][energy_item_id] = actual_value |
|
| 185 | if current_datetime_utc > end_datetime_utc: |
|
| 186 | end_datetime_utc = current_datetime_utc |
|
| 187 | ||
| 188 | ############################################################################################################ |
|
| 189 | # Step 4: get tariffs |
|
| 190 | ############################################################################################################ |
|
| 191 | print("Step 4: get tariffs") |
|
| 192 | tariff_dict = dict() |
|
| 193 | for energy_item_id in energy_item_list: |
|
| 194 | tariff_dict[energy_item_id] = tariff.get_energy_item_tariffs(store['cost_center_id'], |
|
| 195 | energy_item_id, |
|
| 196 | start_datetime_utc, |
|
| 197 | end_datetime_utc) |
|
| 198 | ############################################################################################################ |
|
| 199 | # Step 5: calculate billing by multiplying energy with tariff |
|
| 200 | ############################################################################################################ |
|
| 201 | print("Step 5: calculate billing by multiplying energy with tariff") |
|
| 202 | billing_dict = dict() |
|
| 203 | ||
| 204 | if len(energy_dict) > 0: |
|
| 205 | for current_datetime_utc in energy_dict.keys(): |
|
| 206 | billing_dict[current_datetime_utc] = dict() |
|
| 207 | for energy_item_id in energy_item_list: |
|
| 208 | current_tariff = tariff_dict[energy_item_id].get(current_datetime_utc) |
|
| 209 | current_energy = energy_dict[current_datetime_utc].get(energy_item_id) |
|
| 210 | if current_tariff is not None \ |
|
| 211 | and isinstance(current_tariff, Decimal) \ |
|
| 212 | and current_energy is not None \ |
|
| 213 | and isinstance(current_energy, Decimal): |
|
| 214 | billing_dict[current_datetime_utc][energy_item_id] = \ |
|
| 215 | current_energy * current_tariff |
|
| 216 | ||
| 217 | if len(billing_dict[current_datetime_utc]) == 0: |
|
| 218 | del billing_dict[current_datetime_utc] |
|
| 219 | ||
| 220 | ############################################################################################################ |
|
| 221 | # Step 6: save billing data to billing database |
|
| 222 | ############################################################################################################ |
|
| 223 | print("Step 6: save billing data to billing database") |
|
| 224 | ||
| 225 | if len(billing_dict) > 0: |
|
| 226 | try: |
|
| 227 | add_values = (" INSERT INTO tbl_store_input_item_hourly " |
|
| 228 | " (store_id, " |
|
| 229 | " energy_item_id, " |
|
| 230 | " start_datetime_utc, " |
|
| 231 | " actual_value) " |
|
| 232 | " VALUES ") |
|
| 233 | ||
| 234 | for current_datetime_utc in billing_dict: |
|
| 235 | for energy_item_id in energy_item_list: |
|
| 236 | current_billing = billing_dict[current_datetime_utc].get(energy_item_id) |
|
| 237 | if current_billing is not None and isinstance(current_billing, Decimal): |
|
| 238 | add_values += " (" + str(store['id']) + "," |
|
| 239 | add_values += " " + str(energy_item_id) + "," |
|
| 240 | add_values += "'" + current_datetime_utc.isoformat()[0:19] + "'," |
|
| 241 | add_values += str(billing_dict[current_datetime_utc][energy_item_id]) + "), " |
|
| 242 | print("add_values:" + add_values) |
|
| 243 | # trim ", " at the end of string and then execute |
|
| 244 | cursor_billing_db.execute(add_values[:-2]) |
|
| 245 | cnx_billing_db.commit() |
|
| 246 | except Exception as e: |
|
| 247 | logger.error("Error in step 6 of store_billing_input_item " + str(e)) |
|
| 248 | # break the for store loop |
|
| 249 | break |
|
| 250 | ||
| 251 | # end of for store loop |
|
| 252 | if cnx_system_db: |
|
| 253 | cnx_system_db.close() |
|
| 254 | if cursor_system_db: |
|
| 255 | cursor_system_db.close() |
|
| 256 | ||
| 257 | if cnx_energy_db: |
|
| 258 | cnx_energy_db.close() |
|
| 259 | if cursor_energy_db: |
|
| 260 | cursor_energy_db.close() |
|
| 261 | ||
| 262 | if cnx_billing_db: |
|
| 263 | cnx_billing_db.close() |
|
| 264 | if cursor_billing_db: |
|
| 265 | cursor_billing_db.close() |
|
| 266 | print("go to sleep 300 seconds...") |
|
| 267 | time.sleep(300) |
|
| 268 | print("wake from sleep, and continue to work...") |
|
| 269 | # end of the outermost while loop |
|
| 270 | ||
| @@ 21-268 (lines=248) @@ | ||
| 18 | ######################################################################################################################## |
|
| 19 | ||
| 20 | ||
| 21 | def main(logger): |
|
| 22 | ||
| 23 | while True: |
|
| 24 | # the outermost while loop |
|
| 25 | ################################################################################################################ |
|
| 26 | # Step 1: get all tenants |
|
| 27 | ################################################################################################################ |
|
| 28 | cnx_system_db = None |
|
| 29 | cursor_system_db = None |
|
| 30 | try: |
|
| 31 | cnx_system_db = mysql.connector.connect(**config.myems_system_db) |
|
| 32 | cursor_system_db = cnx_system_db.cursor() |
|
| 33 | except Exception as e: |
|
| 34 | logger.error("Error in step 1.1 of tenant_billing_input_item " + str(e)) |
|
| 35 | if cursor_system_db: |
|
| 36 | cursor_system_db.close() |
|
| 37 | if cnx_system_db: |
|
| 38 | cnx_system_db.close() |
|
| 39 | # sleep and continue the outermost while loop |
|
| 40 | time.sleep(60) |
|
| 41 | continue |
|
| 42 | ||
| 43 | print("Connected to MyEMS System Database") |
|
| 44 | ||
| 45 | try: |
|
| 46 | cursor_system_db.execute(" SELECT id, name, cost_center_id " |
|
| 47 | " FROM tbl_tenants " |
|
| 48 | " ORDER BY id ") |
|
| 49 | rows_tenants = cursor_system_db.fetchall() |
|
| 50 | ||
| 51 | if rows_tenants is None or len(rows_tenants) == 0: |
|
| 52 | print("Step 1.2: There isn't any tenants. ") |
|
| 53 | if cursor_system_db: |
|
| 54 | cursor_system_db.close() |
|
| 55 | if cnx_system_db: |
|
| 56 | cnx_system_db.close() |
|
| 57 | # sleep and continue the outermost while loop |
|
| 58 | time.sleep(60) |
|
| 59 | continue |
|
| 60 | ||
| 61 | tenant_list = list() |
|
| 62 | for row in rows_tenants: |
|
| 63 | tenant_list.append({"id": row[0], "name": row[1], "cost_center_id": row[2]}) |
|
| 64 | ||
| 65 | except Exception as e: |
|
| 66 | logger.error("Error in step 1.2 of tenant_billing_input_item " + str(e)) |
|
| 67 | if cursor_system_db: |
|
| 68 | cursor_system_db.close() |
|
| 69 | if cnx_system_db: |
|
| 70 | cnx_system_db.close() |
|
| 71 | # sleep and continue the outermost while loop |
|
| 72 | time.sleep(60) |
|
| 73 | continue |
|
| 74 | ||
| 75 | print("Step 1.2: Got all tenants from MyEMS System Database") |
|
| 76 | ||
| 77 | cnx_energy_db = None |
|
| 78 | cursor_energy_db = None |
|
| 79 | try: |
|
| 80 | cnx_energy_db = mysql.connector.connect(**config.myems_energy_db) |
|
| 81 | cursor_energy_db = cnx_energy_db.cursor() |
|
| 82 | except Exception as e: |
|
| 83 | logger.error("Error in step 1.3 of tenant_billing_input_item " + str(e)) |
|
| 84 | if cursor_energy_db: |
|
| 85 | cursor_energy_db.close() |
|
| 86 | if cnx_energy_db: |
|
| 87 | cnx_energy_db.close() |
|
| 88 | ||
| 89 | if cursor_system_db: |
|
| 90 | cursor_system_db.close() |
|
| 91 | if cnx_system_db: |
|
| 92 | cnx_system_db.close() |
|
| 93 | # sleep and continue the outermost while loop |
|
| 94 | time.sleep(60) |
|
| 95 | continue |
|
| 96 | ||
| 97 | print("Connected to MyEMS Energy Database") |
|
| 98 | ||
| 99 | cnx_billing_db = None |
|
| 100 | cursor_billing_db = None |
|
| 101 | try: |
|
| 102 | cnx_billing_db = mysql.connector.connect(**config.myems_billing_db) |
|
| 103 | cursor_billing_db = cnx_billing_db.cursor() |
|
| 104 | except Exception as e: |
|
| 105 | logger.error("Error in step 1.4 of tenant_billing_input_item " + str(e)) |
|
| 106 | if cursor_billing_db: |
|
| 107 | cursor_billing_db.close() |
|
| 108 | if cnx_billing_db: |
|
| 109 | cnx_billing_db.close() |
|
| 110 | ||
| 111 | if cursor_energy_db: |
|
| 112 | cursor_energy_db.close() |
|
| 113 | if cnx_energy_db: |
|
| 114 | cnx_energy_db.close() |
|
| 115 | ||
| 116 | if cursor_system_db: |
|
| 117 | cursor_system_db.close() |
|
| 118 | if cnx_system_db: |
|
| 119 | cnx_system_db.close() |
|
| 120 | # sleep and continue the outermost while loop |
|
| 121 | time.sleep(60) |
|
| 122 | continue |
|
| 123 | ||
| 124 | print("Connected to MyEMS Billing Database") |
|
| 125 | ||
| 126 | for tenant in tenant_list: |
|
| 127 | ||
| 128 | ############################################################################################################ |
|
| 129 | # Step 2: get the latest start_datetime_utc |
|
| 130 | ############################################################################################################ |
|
| 131 | print("Step 2: get the latest start_datetime_utc from billing database for " + tenant['name']) |
|
| 132 | try: |
|
| 133 | cursor_billing_db.execute(" SELECT MAX(start_datetime_utc) " |
|
| 134 | " FROM tbl_tenant_input_item_hourly " |
|
| 135 | " WHERE tenant_id = %s ", |
|
| 136 | (tenant['id'], )) |
|
| 137 | row_datetime = cursor_billing_db.fetchone() |
|
| 138 | start_datetime_utc = datetime.strptime(config.start_datetime_utc, '%Y-%m-%d %H:%M:%S') |
|
| 139 | start_datetime_utc = start_datetime_utc.replace(minute=0, second=0, microsecond=0, tzinfo=None) |
|
| 140 | ||
| 141 | if row_datetime is not None and len(row_datetime) > 0 and isinstance(row_datetime[0], datetime): |
|
| 142 | # replace second and microsecond with 0 |
|
| 143 | # note: do not replace minute in case of calculating in half hourly |
|
| 144 | start_datetime_utc = row_datetime[0].replace(second=0, microsecond=0, tzinfo=None) |
|
| 145 | # start from the next time slot |
|
| 146 | start_datetime_utc += timedelta(minutes=config.minutes_to_count) |
|
| 147 | ||
| 148 | print("start_datetime_utc: " + start_datetime_utc.isoformat()[0:19]) |
|
| 149 | except Exception as e: |
|
| 150 | logger.error("Error in step 2 of tenant_billing_input_item " + str(e)) |
|
| 151 | # break the for tenant loop |
|
| 152 | break |
|
| 153 | ||
| 154 | ############################################################################################################ |
|
| 155 | # Step 3: get all energy input data since the latest start_datetime_utc |
|
| 156 | ############################################################################################################ |
|
| 157 | print("Step 3: get all energy input data since the latest start_datetime_utc") |
|
| 158 | ||
| 159 | query = (" SELECT start_datetime_utc, energy_item_id, actual_value " |
|
| 160 | " FROM tbl_tenant_input_item_hourly " |
|
| 161 | " WHERE tenant_id = %s AND start_datetime_utc >= %s " |
|
| 162 | " ORDER BY id ") |
|
| 163 | cursor_energy_db.execute(query, (tenant['id'], start_datetime_utc, )) |
|
| 164 | rows_hourly = cursor_energy_db.fetchall() |
|
| 165 | ||
| 166 | if rows_hourly is None or len(rows_hourly) == 0: |
|
| 167 | print("Step 3: There isn't any energy input data to calculate. ") |
|
| 168 | # continue the for tenant loop |
|
| 169 | continue |
|
| 170 | ||
| 171 | energy_dict = dict() |
|
| 172 | energy_item_list = list() |
|
| 173 | end_datetime_utc = start_datetime_utc |
|
| 174 | for row_hourly in rows_hourly: |
|
| 175 | current_datetime_utc = row_hourly[0] |
|
| 176 | energy_item_id = row_hourly[1] |
|
| 177 | ||
| 178 | if energy_item_id not in energy_item_list: |
|
| 179 | energy_item_list.append(energy_item_id) |
|
| 180 | ||
| 181 | actual_value = row_hourly[2] |
|
| 182 | if energy_dict.get(current_datetime_utc) is None: |
|
| 183 | energy_dict[current_datetime_utc] = dict() |
|
| 184 | energy_dict[current_datetime_utc][energy_item_id] = actual_value |
|
| 185 | if current_datetime_utc > end_datetime_utc: |
|
| 186 | end_datetime_utc = current_datetime_utc |
|
| 187 | ||
| 188 | ############################################################################################################ |
|
| 189 | # Step 4: get tariffs |
|
| 190 | ############################################################################################################ |
|
| 191 | print("Step 4: get tariffs") |
|
| 192 | tariff_dict = dict() |
|
| 193 | for energy_item_id in energy_item_list: |
|
| 194 | tariff_dict[energy_item_id] = tariff.get_energy_item_tariffs(tenant['cost_center_id'], |
|
| 195 | energy_item_id, |
|
| 196 | start_datetime_utc, |
|
| 197 | end_datetime_utc) |
|
| 198 | ############################################################################################################ |
|
| 199 | # Step 5: calculate billing by multiplying energy with tariff |
|
| 200 | ############################################################################################################ |
|
| 201 | print("Step 5: calculate billing by multiplying energy with tariff") |
|
| 202 | billing_dict = dict() |
|
| 203 | ||
| 204 | if len(energy_dict) > 0: |
|
| 205 | for current_datetime_utc in energy_dict.keys(): |
|
| 206 | billing_dict[current_datetime_utc] = dict() |
|
| 207 | for energy_item_id in energy_item_list: |
|
| 208 | current_tariff = tariff_dict[energy_item_id].get(current_datetime_utc) |
|
| 209 | current_energy = energy_dict[current_datetime_utc].get(energy_item_id) |
|
| 210 | if current_tariff is not None \ |
|
| 211 | and isinstance(current_tariff, Decimal) \ |
|
| 212 | and current_energy is not None \ |
|
| 213 | and isinstance(current_energy, Decimal): |
|
| 214 | billing_dict[current_datetime_utc][energy_item_id] = \ |
|
| 215 | current_energy * current_tariff |
|
| 216 | ||
| 217 | if len(billing_dict[current_datetime_utc]) == 0: |
|
| 218 | del billing_dict[current_datetime_utc] |
|
| 219 | ||
| 220 | ############################################################################################################ |
|
| 221 | # Step 6: save billing data to billing database |
|
| 222 | ############################################################################################################ |
|
| 223 | print("Step 6: save billing data to billing database") |
|
| 224 | ||
| 225 | if len(billing_dict) > 0: |
|
| 226 | try: |
|
| 227 | add_values = (" INSERT INTO tbl_tenant_input_item_hourly " |
|
| 228 | " (tenant_id, " |
|
| 229 | " energy_item_id, " |
|
| 230 | " start_datetime_utc, " |
|
| 231 | " actual_value) " |
|
| 232 | " VALUES ") |
|
| 233 | ||
| 234 | for current_datetime_utc in billing_dict: |
|
| 235 | for energy_item_id in energy_item_list: |
|
| 236 | current_billing = billing_dict[current_datetime_utc].get(energy_item_id) |
|
| 237 | if current_billing is not None and isinstance(current_billing, Decimal): |
|
| 238 | add_values += " (" + str(tenant['id']) + "," |
|
| 239 | add_values += " " + str(energy_item_id) + "," |
|
| 240 | add_values += "'" + current_datetime_utc.isoformat()[0:19] + "'," |
|
| 241 | add_values += str(billing_dict[current_datetime_utc][energy_item_id]) + "), " |
|
| 242 | print("add_values:" + add_values) |
|
| 243 | # trim ", " at the end of string and then execute |
|
| 244 | cursor_billing_db.execute(add_values[:-2]) |
|
| 245 | cnx_billing_db.commit() |
|
| 246 | except Exception as e: |
|
| 247 | logger.error("Error in step 6 of tenant_billing_input_item " + str(e)) |
|
| 248 | # break the for tenant loop |
|
| 249 | break |
|
| 250 | ||
| 251 | # end of for tenant loop |
|
| 252 | if cnx_system_db: |
|
| 253 | cnx_system_db.close() |
|
| 254 | if cursor_system_db: |
|
| 255 | cursor_system_db.close() |
|
| 256 | ||
| 257 | if cnx_energy_db: |
|
| 258 | cnx_energy_db.close() |
|
| 259 | if cursor_energy_db: |
|
| 260 | cursor_energy_db.close() |
|
| 261 | ||
| 262 | if cnx_billing_db: |
|
| 263 | cnx_billing_db.close() |
|
| 264 | if cursor_billing_db: |
|
| 265 | cursor_billing_db.close() |
|
| 266 | print("go to sleep 300 seconds...") |
|
| 267 | time.sleep(300) |
|
| 268 | print("wake from sleep, and continue to work...") |
|
| 269 | # end of the outermost while loop |
|
| 270 | ||
| @@ 21-268 (lines=248) @@ | ||
| 18 | ######################################################################################################################## |
|
| 19 | ||
| 20 | ||
| 21 | def main(logger): |
|
| 22 | ||
| 23 | while True: |
|
| 24 | # the outermost while loop |
|
| 25 | ################################################################################################################ |
|
| 26 | # Step 1: get all spaces |
|
| 27 | ################################################################################################################ |
|
| 28 | cnx_system_db = None |
|
| 29 | cursor_system_db = None |
|
| 30 | try: |
|
| 31 | cnx_system_db = mysql.connector.connect(**config.myems_system_db) |
|
| 32 | cursor_system_db = cnx_system_db.cursor() |
|
| 33 | except Exception as e: |
|
| 34 | logger.error("Error in step 1.1 of space_billing_input_category " + str(e)) |
|
| 35 | if cursor_system_db: |
|
| 36 | cursor_system_db.close() |
|
| 37 | if cnx_system_db: |
|
| 38 | cnx_system_db.close() |
|
| 39 | # sleep and continue the outermost while loop |
|
| 40 | time.sleep(60) |
|
| 41 | continue |
|
| 42 | ||
| 43 | print("Connected to MyEMS System Database") |
|
| 44 | ||
| 45 | try: |
|
| 46 | cursor_system_db.execute(" SELECT id, name, cost_center_id " |
|
| 47 | " FROM tbl_spaces " |
|
| 48 | " ORDER BY id ") |
|
| 49 | rows_spaces = cursor_system_db.fetchall() |
|
| 50 | ||
| 51 | if rows_spaces is None or len(rows_spaces) == 0: |
|
| 52 | print("Step 1.2: There isn't any spaces. ") |
|
| 53 | if cursor_system_db: |
|
| 54 | cursor_system_db.close() |
|
| 55 | if cnx_system_db: |
|
| 56 | cnx_system_db.close() |
|
| 57 | # sleep and continue the outermost while loop |
|
| 58 | time.sleep(60) |
|
| 59 | continue |
|
| 60 | ||
| 61 | space_list = list() |
|
| 62 | for row in rows_spaces: |
|
| 63 | space_list.append({"id": row[0], "name": row[1], "cost_center_id": row[2]}) |
|
| 64 | ||
| 65 | except Exception as e: |
|
| 66 | logger.error("Error in step 1.2 of space_billing_input_category " + str(e)) |
|
| 67 | if cursor_system_db: |
|
| 68 | cursor_system_db.close() |
|
| 69 | if cnx_system_db: |
|
| 70 | cnx_system_db.close() |
|
| 71 | # sleep and continue the outermost while loop |
|
| 72 | time.sleep(60) |
|
| 73 | continue |
|
| 74 | ||
| 75 | print("Step 1.2: Got all spaces from MyEMS System Database") |
|
| 76 | ||
| 77 | cnx_energy_db = None |
|
| 78 | cursor_energy_db = None |
|
| 79 | try: |
|
| 80 | cnx_energy_db = mysql.connector.connect(**config.myems_energy_db) |
|
| 81 | cursor_energy_db = cnx_energy_db.cursor() |
|
| 82 | except Exception as e: |
|
| 83 | logger.error("Error in step 1.3 of space_billing_input_category " + str(e)) |
|
| 84 | if cursor_energy_db: |
|
| 85 | cursor_energy_db.close() |
|
| 86 | if cnx_energy_db: |
|
| 87 | cnx_energy_db.close() |
|
| 88 | ||
| 89 | if cursor_system_db: |
|
| 90 | cursor_system_db.close() |
|
| 91 | if cnx_system_db: |
|
| 92 | cnx_system_db.close() |
|
| 93 | # sleep and continue the outermost while loop |
|
| 94 | time.sleep(60) |
|
| 95 | continue |
|
| 96 | ||
| 97 | print("Connected to MyEMS Energy Database") |
|
| 98 | ||
| 99 | cnx_billing_db = None |
|
| 100 | cursor_billing_db = None |
|
| 101 | try: |
|
| 102 | cnx_billing_db = mysql.connector.connect(**config.myems_billing_db) |
|
| 103 | cursor_billing_db = cnx_billing_db.cursor() |
|
| 104 | except Exception as e: |
|
| 105 | logger.error("Error in step 1.4 of space_billing_input_category " + str(e)) |
|
| 106 | if cursor_billing_db: |
|
| 107 | cursor_billing_db.close() |
|
| 108 | if cnx_billing_db: |
|
| 109 | cnx_billing_db.close() |
|
| 110 | ||
| 111 | if cursor_energy_db: |
|
| 112 | cursor_energy_db.close() |
|
| 113 | if cnx_energy_db: |
|
| 114 | cnx_energy_db.close() |
|
| 115 | ||
| 116 | if cursor_system_db: |
|
| 117 | cursor_system_db.close() |
|
| 118 | if cnx_system_db: |
|
| 119 | cnx_system_db.close() |
|
| 120 | # sleep and continue the outermost while loop |
|
| 121 | time.sleep(60) |
|
| 122 | continue |
|
| 123 | ||
| 124 | print("Connected to MyEMS Billing Database") |
|
| 125 | ||
| 126 | for space in space_list: |
|
| 127 | ||
| 128 | ############################################################################################################ |
|
| 129 | # Step 2: get the latest start_datetime_utc |
|
| 130 | ############################################################################################################ |
|
| 131 | print("Step 2: get the latest start_datetime_utc from billing database for " + space['name']) |
|
| 132 | try: |
|
| 133 | cursor_billing_db.execute(" SELECT MAX(start_datetime_utc) " |
|
| 134 | " FROM tbl_space_input_category_hourly " |
|
| 135 | " WHERE space_id = %s ", |
|
| 136 | (space['id'], )) |
|
| 137 | row_datetime = cursor_billing_db.fetchone() |
|
| 138 | start_datetime_utc = datetime.strptime(config.start_datetime_utc, '%Y-%m-%d %H:%M:%S') |
|
| 139 | start_datetime_utc = start_datetime_utc.replace(minute=0, second=0, microsecond=0, tzinfo=None) |
|
| 140 | ||
| 141 | if row_datetime is not None and len(row_datetime) > 0 and isinstance(row_datetime[0], datetime): |
|
| 142 | # replace second and microsecond with 0 |
|
| 143 | # note: do not replace minute in case of calculating in half hourly |
|
| 144 | start_datetime_utc = row_datetime[0].replace(second=0, microsecond=0, tzinfo=None) |
|
| 145 | # start from the next time slot |
|
| 146 | start_datetime_utc += timedelta(minutes=config.minutes_to_count) |
|
| 147 | ||
| 148 | print("start_datetime_utc: " + start_datetime_utc.isoformat()[0:19]) |
|
| 149 | except Exception as e: |
|
| 150 | logger.error("Error in step 2 of space_billing_input_category " + str(e)) |
|
| 151 | # break the for space loop |
|
| 152 | break |
|
| 153 | ||
| 154 | ############################################################################################################ |
|
| 155 | # Step 3: get all energy input data since the latest start_datetime_utc |
|
| 156 | ############################################################################################################ |
|
| 157 | print("Step 3: get all energy input data since the latest start_datetime_utc") |
|
| 158 | ||
| 159 | query = (" SELECT start_datetime_utc, energy_category_id, actual_value " |
|
| 160 | " FROM tbl_space_input_category_hourly " |
|
| 161 | " WHERE space_id = %s AND start_datetime_utc >= %s " |
|
| 162 | " ORDER BY id ") |
|
| 163 | cursor_energy_db.execute(query, (space['id'], start_datetime_utc, )) |
|
| 164 | rows_hourly = cursor_energy_db.fetchall() |
|
| 165 | ||
| 166 | if rows_hourly is None or len(rows_hourly) == 0: |
|
| 167 | print("Step 3: There isn't any energy input data to calculate. ") |
|
| 168 | # continue the for space loop |
|
| 169 | continue |
|
| 170 | ||
| 171 | energy_dict = dict() |
|
| 172 | energy_category_list = list() |
|
| 173 | end_datetime_utc = start_datetime_utc |
|
| 174 | for row_hourly in rows_hourly: |
|
| 175 | current_datetime_utc = row_hourly[0] |
|
| 176 | energy_category_id = row_hourly[1] |
|
| 177 | ||
| 178 | if energy_category_id not in energy_category_list: |
|
| 179 | energy_category_list.append(energy_category_id) |
|
| 180 | ||
| 181 | actual_value = row_hourly[2] |
|
| 182 | if energy_dict.get(current_datetime_utc) is None: |
|
| 183 | energy_dict[current_datetime_utc] = dict() |
|
| 184 | energy_dict[current_datetime_utc][energy_category_id] = actual_value |
|
| 185 | if current_datetime_utc > end_datetime_utc: |
|
| 186 | end_datetime_utc = current_datetime_utc |
|
| 187 | ||
| 188 | ############################################################################################################ |
|
| 189 | # Step 4: get tariffs |
|
| 190 | ############################################################################################################ |
|
| 191 | print("Step 4: get tariffs") |
|
| 192 | tariff_dict = dict() |
|
| 193 | for energy_category_id in energy_category_list: |
|
| 194 | tariff_dict[energy_category_id] = tariff.get_energy_category_tariffs(space['cost_center_id'], |
|
| 195 | energy_category_id, |
|
| 196 | start_datetime_utc, |
|
| 197 | end_datetime_utc) |
|
| 198 | ############################################################################################################ |
|
| 199 | # Step 5: calculate billing by multiplying energy with tariff |
|
| 200 | ############################################################################################################ |
|
| 201 | print("Step 5: calculate billing by multiplying energy with tariff") |
|
| 202 | billing_dict = dict() |
|
| 203 | ||
| 204 | if len(energy_dict) > 0: |
|
| 205 | for current_datetime_utc in energy_dict.keys(): |
|
| 206 | billing_dict[current_datetime_utc] = dict() |
|
| 207 | for energy_category_id in energy_category_list: |
|
| 208 | current_tariff = tariff_dict[energy_category_id].get(current_datetime_utc) |
|
| 209 | current_energy = energy_dict[current_datetime_utc].get(energy_category_id) |
|
| 210 | if current_tariff is not None \ |
|
| 211 | and isinstance(current_tariff, Decimal) \ |
|
| 212 | and current_energy is not None \ |
|
| 213 | and isinstance(current_energy, Decimal): |
|
| 214 | billing_dict[current_datetime_utc][energy_category_id] = \ |
|
| 215 | current_energy * current_tariff |
|
| 216 | ||
| 217 | if len(billing_dict[current_datetime_utc]) == 0: |
|
| 218 | del billing_dict[current_datetime_utc] |
|
| 219 | ||
| 220 | ############################################################################################################ |
|
| 221 | # Step 6: save billing data to billing database |
|
| 222 | ############################################################################################################ |
|
| 223 | print("Step 6: save billing data to billing database") |
|
| 224 | ||
| 225 | if len(billing_dict) > 0: |
|
| 226 | try: |
|
| 227 | add_values = (" INSERT INTO tbl_space_input_category_hourly " |
|
| 228 | " (space_id, " |
|
| 229 | " energy_category_id, " |
|
| 230 | " start_datetime_utc, " |
|
| 231 | " actual_value) " |
|
| 232 | " VALUES ") |
|
| 233 | ||
| 234 | for current_datetime_utc in billing_dict: |
|
| 235 | for energy_category_id in energy_category_list: |
|
| 236 | current_billing = billing_dict[current_datetime_utc].get(energy_category_id) |
|
| 237 | if current_billing is not None and isinstance(current_billing, Decimal): |
|
| 238 | add_values += " (" + str(space['id']) + "," |
|
| 239 | add_values += " " + str(energy_category_id) + "," |
|
| 240 | add_values += "'" + current_datetime_utc.isoformat()[0:19] + "'," |
|
| 241 | add_values += str(billing_dict[current_datetime_utc][energy_category_id]) + "), " |
|
| 242 | print("add_values:" + add_values) |
|
| 243 | # trim ", " at the end of string and then execute |
|
| 244 | cursor_billing_db.execute(add_values[:-2]) |
|
| 245 | cnx_billing_db.commit() |
|
| 246 | except Exception as e: |
|
| 247 | logger.error("Error in step 6 of space_billing_input_category " + str(e)) |
|
| 248 | # break the for space loop |
|
| 249 | break |
|
| 250 | ||
| 251 | # end of for space loop |
|
| 252 | if cnx_system_db: |
|
| 253 | cnx_system_db.close() |
|
| 254 | if cursor_system_db: |
|
| 255 | cursor_system_db.close() |
|
| 256 | ||
| 257 | if cnx_energy_db: |
|
| 258 | cnx_energy_db.close() |
|
| 259 | if cursor_energy_db: |
|
| 260 | cursor_energy_db.close() |
|
| 261 | ||
| 262 | if cnx_billing_db: |
|
| 263 | cnx_billing_db.close() |
|
| 264 | if cursor_billing_db: |
|
| 265 | cursor_billing_db.close() |
|
| 266 | print("go to sleep 300 seconds...") |
|
| 267 | time.sleep(300) |
|
| 268 | print("wake from sleep, and continue to work...") |
|
| 269 | # end of the outermost while loop |
|
| 270 | ||
| @@ 21-268 (lines=248) @@ | ||
| 18 | ######################################################################################################################## |
|
| 19 | ||
| 20 | ||
| 21 | def main(logger): |
|
| 22 | ||
| 23 | while True: |
|
| 24 | # the outermost while loop |
|
| 25 | ################################################################################################################ |
|
| 26 | # Step 1: get all equipments |
|
| 27 | ################################################################################################################ |
|
| 28 | cnx_system_db = None |
|
| 29 | cursor_system_db = None |
|
| 30 | try: |
|
| 31 | cnx_system_db = mysql.connector.connect(**config.myems_system_db) |
|
| 32 | cursor_system_db = cnx_system_db.cursor() |
|
| 33 | except Exception as e: |
|
| 34 | logger.error("Error in step 1.1 of equipment_billing_input_category " + str(e)) |
|
| 35 | if cursor_system_db: |
|
| 36 | cursor_system_db.close() |
|
| 37 | if cnx_system_db: |
|
| 38 | cnx_system_db.close() |
|
| 39 | # sleep and continue the outermost while loop |
|
| 40 | time.sleep(60) |
|
| 41 | continue |
|
| 42 | ||
| 43 | print("Connected to MyEMS System Database") |
|
| 44 | ||
| 45 | try: |
|
| 46 | cursor_system_db.execute(" SELECT id, name, cost_center_id " |
|
| 47 | " FROM tbl_equipments " |
|
| 48 | " ORDER BY id ") |
|
| 49 | rows_equipments = cursor_system_db.fetchall() |
|
| 50 | ||
| 51 | if rows_equipments is None or len(rows_equipments) == 0: |
|
| 52 | print("Step 1.2: There isn't any equipments. ") |
|
| 53 | if cursor_system_db: |
|
| 54 | cursor_system_db.close() |
|
| 55 | if cnx_system_db: |
|
| 56 | cnx_system_db.close() |
|
| 57 | # sleep and continue the outermost while loop |
|
| 58 | time.sleep(60) |
|
| 59 | continue |
|
| 60 | ||
| 61 | equipment_list = list() |
|
| 62 | for row in rows_equipments: |
|
| 63 | equipment_list.append({"id": row[0], "name": row[1], "cost_center_id": row[2]}) |
|
| 64 | ||
| 65 | except Exception as e: |
|
| 66 | logger.error("Error in step 1.2 of equipment_billing_input_category " + str(e)) |
|
| 67 | if cursor_system_db: |
|
| 68 | cursor_system_db.close() |
|
| 69 | if cnx_system_db: |
|
| 70 | cnx_system_db.close() |
|
| 71 | # sleep and continue the outermost while loop |
|
| 72 | time.sleep(60) |
|
| 73 | continue |
|
| 74 | ||
| 75 | print("Step 1.2: Got all equipments from MyEMS System Database") |
|
| 76 | ||
| 77 | cnx_energy_db = None |
|
| 78 | cursor_energy_db = None |
|
| 79 | try: |
|
| 80 | cnx_energy_db = mysql.connector.connect(**config.myems_energy_db) |
|
| 81 | cursor_energy_db = cnx_energy_db.cursor() |
|
| 82 | except Exception as e: |
|
| 83 | logger.error("Error in step 1.3 of equipment_billing_input_category " + str(e)) |
|
| 84 | if cursor_energy_db: |
|
| 85 | cursor_energy_db.close() |
|
| 86 | if cnx_energy_db: |
|
| 87 | cnx_energy_db.close() |
|
| 88 | ||
| 89 | if cursor_system_db: |
|
| 90 | cursor_system_db.close() |
|
| 91 | if cnx_system_db: |
|
| 92 | cnx_system_db.close() |
|
| 93 | # sleep and continue the outermost while loop |
|
| 94 | time.sleep(60) |
|
| 95 | continue |
|
| 96 | ||
| 97 | print("Connected to MyEMS Energy Database") |
|
| 98 | ||
| 99 | cnx_billing_db = None |
|
| 100 | cursor_billing_db = None |
|
| 101 | try: |
|
| 102 | cnx_billing_db = mysql.connector.connect(**config.myems_billing_db) |
|
| 103 | cursor_billing_db = cnx_billing_db.cursor() |
|
| 104 | except Exception as e: |
|
| 105 | logger.error("Error in step 1.4 of equipment_billing_input_category " + str(e)) |
|
| 106 | if cursor_billing_db: |
|
| 107 | cursor_billing_db.close() |
|
| 108 | if cnx_billing_db: |
|
| 109 | cnx_billing_db.close() |
|
| 110 | ||
| 111 | if cursor_energy_db: |
|
| 112 | cursor_energy_db.close() |
|
| 113 | if cnx_energy_db: |
|
| 114 | cnx_energy_db.close() |
|
| 115 | ||
| 116 | if cursor_system_db: |
|
| 117 | cursor_system_db.close() |
|
| 118 | if cnx_system_db: |
|
| 119 | cnx_system_db.close() |
|
| 120 | # sleep and continue the outermost while loop |
|
| 121 | time.sleep(60) |
|
| 122 | continue |
|
| 123 | ||
| 124 | print("Connected to MyEMS Billing Database") |
|
| 125 | ||
| 126 | for equipment in equipment_list: |
|
| 127 | ||
| 128 | ############################################################################################################ |
|
| 129 | # Step 2: get the latest start_datetime_utc |
|
| 130 | ############################################################################################################ |
|
| 131 | print("Step 2: get the latest start_datetime_utc from billing database for " + equipment['name']) |
|
| 132 | try: |
|
| 133 | cursor_billing_db.execute(" SELECT MAX(start_datetime_utc) " |
|
| 134 | " FROM tbl_equipment_input_category_hourly " |
|
| 135 | " WHERE equipment_id = %s ", |
|
| 136 | (equipment['id'], )) |
|
| 137 | row_datetime = cursor_billing_db.fetchone() |
|
| 138 | start_datetime_utc = datetime.strptime(config.start_datetime_utc, '%Y-%m-%d %H:%M:%S') |
|
| 139 | start_datetime_utc = start_datetime_utc.replace(minute=0, second=0, microsecond=0, tzinfo=None) |
|
| 140 | ||
| 141 | if row_datetime is not None and len(row_datetime) > 0 and isinstance(row_datetime[0], datetime): |
|
| 142 | # replace second and microsecond with 0 |
|
| 143 | # note: do not replace minute in case of calculating in half hourly |
|
| 144 | start_datetime_utc = row_datetime[0].replace(second=0, microsecond=0, tzinfo=None) |
|
| 145 | # start from the next time slot |
|
| 146 | start_datetime_utc += timedelta(minutes=config.minutes_to_count) |
|
| 147 | ||
| 148 | print("start_datetime_utc: " + start_datetime_utc.isoformat()[0:19]) |
|
| 149 | except Exception as e: |
|
| 150 | logger.error("Error in step 2 of equipment_billing_input_category " + str(e)) |
|
| 151 | # break the for equipment loop |
|
| 152 | break |
|
| 153 | ||
| 154 | ############################################################################################################ |
|
| 155 | # Step 3: get all energy input data since the latest start_datetime_utc |
|
| 156 | ############################################################################################################ |
|
| 157 | print("Step 3: get all energy input data since the latest start_datetime_utc") |
|
| 158 | ||
| 159 | query = (" SELECT start_datetime_utc, energy_category_id, actual_value " |
|
| 160 | " FROM tbl_equipment_input_category_hourly " |
|
| 161 | " WHERE equipment_id = %s AND start_datetime_utc >= %s " |
|
| 162 | " ORDER BY id ") |
|
| 163 | cursor_energy_db.execute(query, (equipment['id'], start_datetime_utc, )) |
|
| 164 | rows_hourly = cursor_energy_db.fetchall() |
|
| 165 | ||
| 166 | if rows_hourly is None or len(rows_hourly) == 0: |
|
| 167 | print("Step 3: There isn't any energy input data to calculate. ") |
|
| 168 | # continue the for equipment loop |
|
| 169 | continue |
|
| 170 | ||
| 171 | energy_dict = dict() |
|
| 172 | energy_category_list = list() |
|
| 173 | end_datetime_utc = start_datetime_utc |
|
| 174 | for row_hourly in rows_hourly: |
|
| 175 | current_datetime_utc = row_hourly[0] |
|
| 176 | energy_category_id = row_hourly[1] |
|
| 177 | ||
| 178 | if energy_category_id not in energy_category_list: |
|
| 179 | energy_category_list.append(energy_category_id) |
|
| 180 | ||
| 181 | actual_value = row_hourly[2] |
|
| 182 | if energy_dict.get(current_datetime_utc) is None: |
|
| 183 | energy_dict[current_datetime_utc] = dict() |
|
| 184 | energy_dict[current_datetime_utc][energy_category_id] = actual_value |
|
| 185 | if current_datetime_utc > end_datetime_utc: |
|
| 186 | end_datetime_utc = current_datetime_utc |
|
| 187 | ||
| 188 | ############################################################################################################ |
|
| 189 | # Step 4: get tariffs |
|
| 190 | ############################################################################################################ |
|
| 191 | print("Step 4: get tariffs") |
|
| 192 | tariff_dict = dict() |
|
| 193 | for energy_category_id in energy_category_list: |
|
| 194 | tariff_dict[energy_category_id] = tariff.get_energy_category_tariffs(equipment['cost_center_id'], |
|
| 195 | energy_category_id, |
|
| 196 | start_datetime_utc, |
|
| 197 | end_datetime_utc) |
|
| 198 | ############################################################################################################ |
|
| 199 | # Step 5: calculate billing by multiplying energy with tariff |
|
| 200 | ############################################################################################################ |
|
| 201 | print("Step 5: calculate billing by multiplying energy with tariff") |
|
| 202 | billing_dict = dict() |
|
| 203 | ||
| 204 | if len(energy_dict) > 0: |
|
| 205 | for current_datetime_utc in energy_dict.keys(): |
|
| 206 | billing_dict[current_datetime_utc] = dict() |
|
| 207 | for energy_category_id in energy_category_list: |
|
| 208 | current_tariff = tariff_dict[energy_category_id].get(current_datetime_utc) |
|
| 209 | current_energy = energy_dict[current_datetime_utc].get(energy_category_id) |
|
| 210 | if current_tariff is not None \ |
|
| 211 | and isinstance(current_tariff, Decimal) \ |
|
| 212 | and current_energy is not None \ |
|
| 213 | and isinstance(current_energy, Decimal): |
|
| 214 | billing_dict[current_datetime_utc][energy_category_id] = \ |
|
| 215 | current_energy * current_tariff |
|
| 216 | ||
| 217 | if len(billing_dict[current_datetime_utc]) == 0: |
|
| 218 | del billing_dict[current_datetime_utc] |
|
| 219 | ||
| 220 | ############################################################################################################ |
|
| 221 | # Step 6: save billing data to billing database |
|
| 222 | ############################################################################################################ |
|
| 223 | print("Step 6: save billing data to billing database") |
|
| 224 | ||
| 225 | if len(billing_dict) > 0: |
|
| 226 | try: |
|
| 227 | add_values = (" INSERT INTO tbl_equipment_input_category_hourly " |
|
| 228 | " (equipment_id, " |
|
| 229 | " energy_category_id, " |
|
| 230 | " start_datetime_utc, " |
|
| 231 | " actual_value) " |
|
| 232 | " VALUES ") |
|
| 233 | ||
| 234 | for current_datetime_utc in billing_dict: |
|
| 235 | for energy_category_id in energy_category_list: |
|
| 236 | current_billing = billing_dict[current_datetime_utc].get(energy_category_id) |
|
| 237 | if current_billing is not None and isinstance(current_billing, Decimal): |
|
| 238 | add_values += " (" + str(equipment['id']) + "," |
|
| 239 | add_values += " " + str(energy_category_id) + "," |
|
| 240 | add_values += "'" + current_datetime_utc.isoformat()[0:19] + "'," |
|
| 241 | add_values += str(billing_dict[current_datetime_utc][energy_category_id]) + "), " |
|
| 242 | print("add_values:" + add_values) |
|
| 243 | # trim ", " at the end of string and then execute |
|
| 244 | cursor_billing_db.execute(add_values[:-2]) |
|
| 245 | cnx_billing_db.commit() |
|
| 246 | except Exception as e: |
|
| 247 | logger.error("Error in step 6 of equipment_billing_input_category " + str(e)) |
|
| 248 | # break the for equipment loop |
|
| 249 | break |
|
| 250 | ||
| 251 | # end of for equipment loop |
|
| 252 | if cnx_system_db: |
|
| 253 | cnx_system_db.close() |
|
| 254 | if cursor_system_db: |
|
| 255 | cursor_system_db.close() |
|
| 256 | ||
| 257 | if cnx_energy_db: |
|
| 258 | cnx_energy_db.close() |
|
| 259 | if cursor_energy_db: |
|
| 260 | cursor_energy_db.close() |
|
| 261 | ||
| 262 | if cnx_billing_db: |
|
| 263 | cnx_billing_db.close() |
|
| 264 | if cursor_billing_db: |
|
| 265 | cursor_billing_db.close() |
|
| 266 | print("go to sleep 300 seconds...") |
|
| 267 | time.sleep(300) |
|
| 268 | print("wake from sleep, and continue to work...") |
|
| 269 | # end of the outermost while loop |
|
| 270 | ||
| @@ 21-268 (lines=248) @@ | ||
| 18 | ######################################################################################################################## |
|
| 19 | ||
| 20 | ||
| 21 | def main(logger): |
|
| 22 | ||
| 23 | while True: |
|
| 24 | # the outermost while loop |
|
| 25 | ################################################################################################################ |
|
| 26 | # Step 1: get all spaces |
|
| 27 | ################################################################################################################ |
|
| 28 | cnx_system_db = None |
|
| 29 | cursor_system_db = None |
|
| 30 | try: |
|
| 31 | cnx_system_db = mysql.connector.connect(**config.myems_system_db) |
|
| 32 | cursor_system_db = cnx_system_db.cursor() |
|
| 33 | except Exception as e: |
|
| 34 | logger.error("Error in step 1.1 of space_billing_input_item " + str(e)) |
|
| 35 | if cursor_system_db: |
|
| 36 | cursor_system_db.close() |
|
| 37 | if cnx_system_db: |
|
| 38 | cnx_system_db.close() |
|
| 39 | # sleep and continue the outermost while loop |
|
| 40 | time.sleep(60) |
|
| 41 | continue |
|
| 42 | ||
| 43 | print("Connected to MyEMS System Database") |
|
| 44 | ||
| 45 | try: |
|
| 46 | cursor_system_db.execute(" SELECT id, name, cost_center_id " |
|
| 47 | " FROM tbl_spaces " |
|
| 48 | " ORDER BY id ") |
|
| 49 | rows_spaces = cursor_system_db.fetchall() |
|
| 50 | ||
| 51 | if rows_spaces is None or len(rows_spaces) == 0: |
|
| 52 | print("Step 1.2: There isn't any spaces. ") |
|
| 53 | if cursor_system_db: |
|
| 54 | cursor_system_db.close() |
|
| 55 | if cnx_system_db: |
|
| 56 | cnx_system_db.close() |
|
| 57 | # sleep and continue the outermost while loop |
|
| 58 | time.sleep(60) |
|
| 59 | continue |
|
| 60 | ||
| 61 | space_list = list() |
|
| 62 | for row in rows_spaces: |
|
| 63 | space_list.append({"id": row[0], "name": row[1], "cost_center_id": row[2]}) |
|
| 64 | ||
| 65 | except Exception as e: |
|
| 66 | logger.error("Error in step 1.2 of space_billing_input_item " + str(e)) |
|
| 67 | if cursor_system_db: |
|
| 68 | cursor_system_db.close() |
|
| 69 | if cnx_system_db: |
|
| 70 | cnx_system_db.close() |
|
| 71 | # sleep and continue the outermost while loop |
|
| 72 | time.sleep(60) |
|
| 73 | continue |
|
| 74 | ||
| 75 | print("Step 1.2: Got all spaces from MyEMS System Database") |
|
| 76 | ||
| 77 | cnx_energy_db = None |
|
| 78 | cursor_energy_db = None |
|
| 79 | try: |
|
| 80 | cnx_energy_db = mysql.connector.connect(**config.myems_energy_db) |
|
| 81 | cursor_energy_db = cnx_energy_db.cursor() |
|
| 82 | except Exception as e: |
|
| 83 | logger.error("Error in step 1.3 of space_billing_input_item " + str(e)) |
|
| 84 | if cursor_energy_db: |
|
| 85 | cursor_energy_db.close() |
|
| 86 | if cnx_energy_db: |
|
| 87 | cnx_energy_db.close() |
|
| 88 | ||
| 89 | if cursor_system_db: |
|
| 90 | cursor_system_db.close() |
|
| 91 | if cnx_system_db: |
|
| 92 | cnx_system_db.close() |
|
| 93 | # sleep and continue the outermost while loop |
|
| 94 | time.sleep(60) |
|
| 95 | continue |
|
| 96 | ||
| 97 | print("Connected to MyEMS Energy Database") |
|
| 98 | ||
| 99 | cnx_billing_db = None |
|
| 100 | cursor_billing_db = None |
|
| 101 | try: |
|
| 102 | cnx_billing_db = mysql.connector.connect(**config.myems_billing_db) |
|
| 103 | cursor_billing_db = cnx_billing_db.cursor() |
|
| 104 | except Exception as e: |
|
| 105 | logger.error("Error in step 1.4 of space_billing_input_item " + str(e)) |
|
| 106 | if cursor_billing_db: |
|
| 107 | cursor_billing_db.close() |
|
| 108 | if cnx_billing_db: |
|
| 109 | cnx_billing_db.close() |
|
| 110 | ||
| 111 | if cursor_energy_db: |
|
| 112 | cursor_energy_db.close() |
|
| 113 | if cnx_energy_db: |
|
| 114 | cnx_energy_db.close() |
|
| 115 | ||
| 116 | if cursor_system_db: |
|
| 117 | cursor_system_db.close() |
|
| 118 | if cnx_system_db: |
|
| 119 | cnx_system_db.close() |
|
| 120 | # sleep and continue the outermost while loop |
|
| 121 | time.sleep(60) |
|
| 122 | continue |
|
| 123 | ||
| 124 | print("Connected to MyEMS Billing Database") |
|
| 125 | ||
| 126 | for space in space_list: |
|
| 127 | ||
| 128 | ############################################################################################################ |
|
| 129 | # Step 2: get the latest start_datetime_utc |
|
| 130 | ############################################################################################################ |
|
| 131 | print("Step 2: get the latest start_datetime_utc from billing database for " + space['name']) |
|
| 132 | try: |
|
| 133 | cursor_billing_db.execute(" SELECT MAX(start_datetime_utc) " |
|
| 134 | " FROM tbl_space_input_item_hourly " |
|
| 135 | " WHERE space_id = %s ", |
|
| 136 | (space['id'], )) |
|
| 137 | row_datetime = cursor_billing_db.fetchone() |
|
| 138 | start_datetime_utc = datetime.strptime(config.start_datetime_utc, '%Y-%m-%d %H:%M:%S') |
|
| 139 | start_datetime_utc = start_datetime_utc.replace(minute=0, second=0, microsecond=0, tzinfo=None) |
|
| 140 | ||
| 141 | if row_datetime is not None and len(row_datetime) > 0 and isinstance(row_datetime[0], datetime): |
|
| 142 | # replace second and microsecond with 0 |
|
| 143 | # note: do not replace minute in case of calculating in half hourly |
|
| 144 | start_datetime_utc = row_datetime[0].replace(second=0, microsecond=0, tzinfo=None) |
|
| 145 | # start from the next time slot |
|
| 146 | start_datetime_utc += timedelta(minutes=config.minutes_to_count) |
|
| 147 | ||
| 148 | print("start_datetime_utc: " + start_datetime_utc.isoformat()[0:19]) |
|
| 149 | except Exception as e: |
|
| 150 | logger.error("Error in step 2 of space_billing_input_item " + str(e)) |
|
| 151 | # break the for space loop |
|
| 152 | break |
|
| 153 | ||
| 154 | ############################################################################################################ |
|
| 155 | # Step 3: get all energy input data since the latest start_datetime_utc |
|
| 156 | ############################################################################################################ |
|
| 157 | print("Step 3: get all energy input data since the latest start_datetime_utc") |
|
| 158 | ||
| 159 | query = (" SELECT start_datetime_utc, energy_item_id, actual_value " |
|
| 160 | " FROM tbl_space_input_item_hourly " |
|
| 161 | " WHERE space_id = %s AND start_datetime_utc >= %s " |
|
| 162 | " ORDER BY id ") |
|
| 163 | cursor_energy_db.execute(query, (space['id'], start_datetime_utc, )) |
|
| 164 | rows_hourly = cursor_energy_db.fetchall() |
|
| 165 | ||
| 166 | if rows_hourly is None or len(rows_hourly) == 0: |
|
| 167 | print("Step 3: There isn't any energy input data to calculate. ") |
|
| 168 | # continue the for space loop |
|
| 169 | continue |
|
| 170 | ||
| 171 | energy_dict = dict() |
|
| 172 | energy_item_list = list() |
|
| 173 | end_datetime_utc = start_datetime_utc |
|
| 174 | for row_hourly in rows_hourly: |
|
| 175 | current_datetime_utc = row_hourly[0] |
|
| 176 | energy_item_id = row_hourly[1] |
|
| 177 | ||
| 178 | if energy_item_id not in energy_item_list: |
|
| 179 | energy_item_list.append(energy_item_id) |
|
| 180 | ||
| 181 | actual_value = row_hourly[2] |
|
| 182 | if energy_dict.get(current_datetime_utc) is None: |
|
| 183 | energy_dict[current_datetime_utc] = dict() |
|
| 184 | energy_dict[current_datetime_utc][energy_item_id] = actual_value |
|
| 185 | if current_datetime_utc > end_datetime_utc: |
|
| 186 | end_datetime_utc = current_datetime_utc |
|
| 187 | ||
| 188 | ############################################################################################################ |
|
| 189 | # Step 4: get tariffs |
|
| 190 | ############################################################################################################ |
|
| 191 | print("Step 4: get tariffs") |
|
| 192 | tariff_dict = dict() |
|
| 193 | for energy_item_id in energy_item_list: |
|
| 194 | tariff_dict[energy_item_id] = tariff.get_energy_item_tariffs(space['cost_center_id'], |
|
| 195 | energy_item_id, |
|
| 196 | start_datetime_utc, |
|
| 197 | end_datetime_utc) |
|
| 198 | ############################################################################################################ |
|
| 199 | # Step 5: calculate billing by multiplying energy with tariff |
|
| 200 | ############################################################################################################ |
|
| 201 | print("Step 5: calculate billing by multiplying energy with tariff") |
|
| 202 | billing_dict = dict() |
|
| 203 | ||
| 204 | if len(energy_dict) > 0: |
|
| 205 | for current_datetime_utc in energy_dict.keys(): |
|
| 206 | billing_dict[current_datetime_utc] = dict() |
|
| 207 | for energy_item_id in energy_item_list: |
|
| 208 | current_tariff = tariff_dict[energy_item_id].get(current_datetime_utc) |
|
| 209 | current_energy = energy_dict[current_datetime_utc].get(energy_item_id) |
|
| 210 | if current_tariff is not None \ |
|
| 211 | and isinstance(current_tariff, Decimal) \ |
|
| 212 | and current_energy is not None \ |
|
| 213 | and isinstance(current_energy, Decimal): |
|
| 214 | billing_dict[current_datetime_utc][energy_item_id] = \ |
|
| 215 | current_energy * current_tariff |
|
| 216 | ||
| 217 | if len(billing_dict[current_datetime_utc]) == 0: |
|
| 218 | del billing_dict[current_datetime_utc] |
|
| 219 | ||
| 220 | ############################################################################################################ |
|
| 221 | # Step 6: save billing data to billing database |
|
| 222 | ############################################################################################################ |
|
| 223 | print("Step 6: save billing data to billing database") |
|
| 224 | ||
| 225 | if len(billing_dict) > 0: |
|
| 226 | try: |
|
| 227 | add_values = (" INSERT INTO tbl_space_input_item_hourly " |
|
| 228 | " (space_id, " |
|
| 229 | " energy_item_id, " |
|
| 230 | " start_datetime_utc, " |
|
| 231 | " actual_value) " |
|
| 232 | " VALUES ") |
|
| 233 | ||
| 234 | for current_datetime_utc in billing_dict: |
|
| 235 | for energy_item_id in energy_item_list: |
|
| 236 | current_billing = billing_dict[current_datetime_utc].get(energy_item_id) |
|
| 237 | if current_billing is not None and isinstance(current_billing, Decimal): |
|
| 238 | add_values += " (" + str(space['id']) + "," |
|
| 239 | add_values += " " + str(energy_item_id) + "," |
|
| 240 | add_values += "'" + current_datetime_utc.isoformat()[0:19] + "'," |
|
| 241 | add_values += str(billing_dict[current_datetime_utc][energy_item_id]) + "), " |
|
| 242 | print("add_values:" + add_values) |
|
| 243 | # trim ", " at the end of string and then execute |
|
| 244 | cursor_billing_db.execute(add_values[:-2]) |
|
| 245 | cnx_billing_db.commit() |
|
| 246 | except Exception as e: |
|
| 247 | logger.error("Error in step 6 of space_billing_input_item " + str(e)) |
|
| 248 | # break the for space loop |
|
| 249 | break |
|
| 250 | ||
| 251 | # end of for space loop |
|
| 252 | if cnx_system_db: |
|
| 253 | cnx_system_db.close() |
|
| 254 | if cursor_system_db: |
|
| 255 | cursor_system_db.close() |
|
| 256 | ||
| 257 | if cnx_energy_db: |
|
| 258 | cnx_energy_db.close() |
|
| 259 | if cursor_energy_db: |
|
| 260 | cursor_energy_db.close() |
|
| 261 | ||
| 262 | if cnx_billing_db: |
|
| 263 | cnx_billing_db.close() |
|
| 264 | if cursor_billing_db: |
|
| 265 | cursor_billing_db.close() |
|
| 266 | print("go to sleep 300 seconds...") |
|
| 267 | time.sleep(300) |
|
| 268 | print("wake from sleep, and continue to work...") |
|
| 269 | # end of the outermost while loop |
|
| 270 | ||
| @@ 21-268 (lines=248) @@ | ||
| 18 | ######################################################################################################################## |
|
| 19 | ||
| 20 | ||
| 21 | def main(logger): |
|
| 22 | ||
| 23 | while True: |
|
| 24 | # the outermost while loop |
|
| 25 | ################################################################################################################ |
|
| 26 | # Step 1: get all tenants |
|
| 27 | ################################################################################################################ |
|
| 28 | cnx_system_db = None |
|
| 29 | cursor_system_db = None |
|
| 30 | try: |
|
| 31 | cnx_system_db = mysql.connector.connect(**config.myems_system_db) |
|
| 32 | cursor_system_db = cnx_system_db.cursor() |
|
| 33 | except Exception as e: |
|
| 34 | logger.error("Error in step 1.1 of tenant_billing_input_category " + str(e)) |
|
| 35 | if cursor_system_db: |
|
| 36 | cursor_system_db.close() |
|
| 37 | if cnx_system_db: |
|
| 38 | cnx_system_db.close() |
|
| 39 | # sleep and continue the outermost while loop |
|
| 40 | time.sleep(60) |
|
| 41 | continue |
|
| 42 | ||
| 43 | print("Connected to MyEMS System Database") |
|
| 44 | ||
| 45 | try: |
|
| 46 | cursor_system_db.execute(" SELECT id, name, cost_center_id " |
|
| 47 | " FROM tbl_tenants " |
|
| 48 | " ORDER BY id ") |
|
| 49 | rows_tenants = cursor_system_db.fetchall() |
|
| 50 | ||
| 51 | if rows_tenants is None or len(rows_tenants) == 0: |
|
| 52 | print("Step 1.2: There isn't any tenants. ") |
|
| 53 | if cursor_system_db: |
|
| 54 | cursor_system_db.close() |
|
| 55 | if cnx_system_db: |
|
| 56 | cnx_system_db.close() |
|
| 57 | # sleep and continue the outermost while loop |
|
| 58 | time.sleep(60) |
|
| 59 | continue |
|
| 60 | ||
| 61 | tenant_list = list() |
|
| 62 | for row in rows_tenants: |
|
| 63 | tenant_list.append({"id": row[0], "name": row[1], "cost_center_id": row[2]}) |
|
| 64 | ||
| 65 | except Exception as e: |
|
| 66 | logger.error("Error in step 1.2 of tenant_billing_input_category " + str(e)) |
|
| 67 | if cursor_system_db: |
|
| 68 | cursor_system_db.close() |
|
| 69 | if cnx_system_db: |
|
| 70 | cnx_system_db.close() |
|
| 71 | # sleep and continue the outermost while loop |
|
| 72 | time.sleep(60) |
|
| 73 | continue |
|
| 74 | ||
| 75 | print("Step 1.2: Got all tenants from MyEMS System Database") |
|
| 76 | ||
| 77 | cnx_energy_db = None |
|
| 78 | cursor_energy_db = None |
|
| 79 | try: |
|
| 80 | cnx_energy_db = mysql.connector.connect(**config.myems_energy_db) |
|
| 81 | cursor_energy_db = cnx_energy_db.cursor() |
|
| 82 | except Exception as e: |
|
| 83 | logger.error("Error in step 1.3 of tenant_billing_input_category " + str(e)) |
|
| 84 | if cursor_energy_db: |
|
| 85 | cursor_energy_db.close() |
|
| 86 | if cnx_energy_db: |
|
| 87 | cnx_energy_db.close() |
|
| 88 | ||
| 89 | if cursor_system_db: |
|
| 90 | cursor_system_db.close() |
|
| 91 | if cnx_system_db: |
|
| 92 | cnx_system_db.close() |
|
| 93 | # sleep and continue the outermost while loop |
|
| 94 | time.sleep(60) |
|
| 95 | continue |
|
| 96 | ||
| 97 | print("Connected to MyEMS Energy Database") |
|
| 98 | ||
| 99 | cnx_billing_db = None |
|
| 100 | cursor_billing_db = None |
|
| 101 | try: |
|
| 102 | cnx_billing_db = mysql.connector.connect(**config.myems_billing_db) |
|
| 103 | cursor_billing_db = cnx_billing_db.cursor() |
|
| 104 | except Exception as e: |
|
| 105 | logger.error("Error in step 1.4 of tenant_billing_input_category " + str(e)) |
|
| 106 | if cursor_billing_db: |
|
| 107 | cursor_billing_db.close() |
|
| 108 | if cnx_billing_db: |
|
| 109 | cnx_billing_db.close() |
|
| 110 | ||
| 111 | if cursor_energy_db: |
|
| 112 | cursor_energy_db.close() |
|
| 113 | if cnx_energy_db: |
|
| 114 | cnx_energy_db.close() |
|
| 115 | ||
| 116 | if cursor_system_db: |
|
| 117 | cursor_system_db.close() |
|
| 118 | if cnx_system_db: |
|
| 119 | cnx_system_db.close() |
|
| 120 | # sleep and continue the outermost while loop |
|
| 121 | time.sleep(60) |
|
| 122 | continue |
|
| 123 | ||
| 124 | print("Connected to MyEMS Billing Database") |
|
| 125 | ||
| 126 | for tenant in tenant_list: |
|
| 127 | ||
| 128 | ############################################################################################################ |
|
| 129 | # Step 2: get the latest start_datetime_utc |
|
| 130 | ############################################################################################################ |
|
| 131 | print("Step 2: get the latest start_datetime_utc from billing database for " + tenant['name']) |
|
| 132 | try: |
|
| 133 | cursor_billing_db.execute(" SELECT MAX(start_datetime_utc) " |
|
| 134 | " FROM tbl_tenant_input_category_hourly " |
|
| 135 | " WHERE tenant_id = %s ", |
|
| 136 | (tenant['id'], )) |
|
| 137 | row_datetime = cursor_billing_db.fetchone() |
|
| 138 | start_datetime_utc = datetime.strptime(config.start_datetime_utc, '%Y-%m-%d %H:%M:%S') |
|
| 139 | start_datetime_utc = start_datetime_utc.replace(minute=0, second=0, microsecond=0, tzinfo=None) |
|
| 140 | ||
| 141 | if row_datetime is not None and len(row_datetime) > 0 and isinstance(row_datetime[0], datetime): |
|
| 142 | # replace second and microsecond with 0 |
|
| 143 | # note: do not replace minute in case of calculating in half hourly |
|
| 144 | start_datetime_utc = row_datetime[0].replace(second=0, microsecond=0, tzinfo=None) |
|
| 145 | # start from the next time slot |
|
| 146 | start_datetime_utc += timedelta(minutes=config.minutes_to_count) |
|
| 147 | ||
| 148 | print("start_datetime_utc: " + start_datetime_utc.isoformat()[0:19]) |
|
| 149 | except Exception as e: |
|
| 150 | logger.error("Error in step 2 of tenant_billing_input_category " + str(e)) |
|
| 151 | # break the for tenant loop |
|
| 152 | break |
|
| 153 | ||
| 154 | ############################################################################################################ |
|
| 155 | # Step 3: get all energy input data since the latest start_datetime_utc |
|
| 156 | ############################################################################################################ |
|
| 157 | print("Step 3: get all energy input data since the latest start_datetime_utc") |
|
| 158 | ||
| 159 | query = (" SELECT start_datetime_utc, energy_category_id, actual_value " |
|
| 160 | " FROM tbl_tenant_input_category_hourly " |
|
| 161 | " WHERE tenant_id = %s AND start_datetime_utc >= %s " |
|
| 162 | " ORDER BY id ") |
|
| 163 | cursor_energy_db.execute(query, (tenant['id'], start_datetime_utc, )) |
|
| 164 | rows_hourly = cursor_energy_db.fetchall() |
|
| 165 | ||
| 166 | if rows_hourly is None or len(rows_hourly) == 0: |
|
| 167 | print("Step 3: There isn't any energy input data to calculate. ") |
|
| 168 | # continue the for tenant loop |
|
| 169 | continue |
|
| 170 | ||
| 171 | energy_dict = dict() |
|
| 172 | energy_category_list = list() |
|
| 173 | end_datetime_utc = start_datetime_utc |
|
| 174 | for row_hourly in rows_hourly: |
|
| 175 | current_datetime_utc = row_hourly[0] |
|
| 176 | energy_category_id = row_hourly[1] |
|
| 177 | ||
| 178 | if energy_category_id not in energy_category_list: |
|
| 179 | energy_category_list.append(energy_category_id) |
|
| 180 | ||
| 181 | actual_value = row_hourly[2] |
|
| 182 | if energy_dict.get(current_datetime_utc) is None: |
|
| 183 | energy_dict[current_datetime_utc] = dict() |
|
| 184 | energy_dict[current_datetime_utc][energy_category_id] = actual_value |
|
| 185 | if current_datetime_utc > end_datetime_utc: |
|
| 186 | end_datetime_utc = current_datetime_utc |
|
| 187 | ||
| 188 | ############################################################################################################ |
|
| 189 | # Step 4: get tariffs |
|
| 190 | ############################################################################################################ |
|
| 191 | print("Step 4: get tariffs") |
|
| 192 | tariff_dict = dict() |
|
| 193 | for energy_category_id in energy_category_list: |
|
| 194 | tariff_dict[energy_category_id] = tariff.get_energy_category_tariffs(tenant['cost_center_id'], |
|
| 195 | energy_category_id, |
|
| 196 | start_datetime_utc, |
|
| 197 | end_datetime_utc) |
|
| 198 | ############################################################################################################ |
|
| 199 | # Step 5: calculate billing by multiplying energy with tariff |
|
| 200 | ############################################################################################################ |
|
| 201 | print("Step 5: calculate billing by multiplying energy with tariff") |
|
| 202 | billing_dict = dict() |
|
| 203 | ||
| 204 | if len(energy_dict) > 0: |
|
| 205 | for current_datetime_utc in energy_dict.keys(): |
|
| 206 | billing_dict[current_datetime_utc] = dict() |
|
| 207 | for energy_category_id in energy_category_list: |
|
| 208 | current_tariff = tariff_dict[energy_category_id].get(current_datetime_utc) |
|
| 209 | current_energy = energy_dict[current_datetime_utc].get(energy_category_id) |
|
| 210 | if current_tariff is not None \ |
|
| 211 | and isinstance(current_tariff, Decimal) \ |
|
| 212 | and current_energy is not None \ |
|
| 213 | and isinstance(current_energy, Decimal): |
|
| 214 | billing_dict[current_datetime_utc][energy_category_id] = \ |
|
| 215 | current_energy * current_tariff |
|
| 216 | ||
| 217 | if len(billing_dict[current_datetime_utc]) == 0: |
|
| 218 | del billing_dict[current_datetime_utc] |
|
| 219 | ||
| 220 | ############################################################################################################ |
|
| 221 | # Step 6: save billing data to billing database |
|
| 222 | ############################################################################################################ |
|
| 223 | print("Step 6: save billing data to billing database") |
|
| 224 | ||
| 225 | if len(billing_dict) > 0: |
|
| 226 | try: |
|
| 227 | add_values = (" INSERT INTO tbl_tenant_input_category_hourly " |
|
| 228 | " (tenant_id, " |
|
| 229 | " energy_category_id, " |
|
| 230 | " start_datetime_utc, " |
|
| 231 | " actual_value) " |
|
| 232 | " VALUES ") |
|
| 233 | ||
| 234 | for current_datetime_utc in billing_dict: |
|
| 235 | for energy_category_id in energy_category_list: |
|
| 236 | current_billing = billing_dict[current_datetime_utc].get(energy_category_id) |
|
| 237 | if current_billing is not None and isinstance(current_billing, Decimal): |
|
| 238 | add_values += " (" + str(tenant['id']) + "," |
|
| 239 | add_values += " " + str(energy_category_id) + "," |
|
| 240 | add_values += "'" + current_datetime_utc.isoformat()[0:19] + "'," |
|
| 241 | add_values += str(billing_dict[current_datetime_utc][energy_category_id]) + "), " |
|
| 242 | print("add_values:" + add_values) |
|
| 243 | # trim ", " at the end of string and then execute |
|
| 244 | cursor_billing_db.execute(add_values[:-2]) |
|
| 245 | cnx_billing_db.commit() |
|
| 246 | except Exception as e: |
|
| 247 | logger.error("Error in step 6 of tenant_billing_input_category " + str(e)) |
|
| 248 | # break the for tenant loop |
|
| 249 | break |
|
| 250 | ||
| 251 | # end of for tenant loop |
|
| 252 | if cnx_system_db: |
|
| 253 | cnx_system_db.close() |
|
| 254 | if cursor_system_db: |
|
| 255 | cursor_system_db.close() |
|
| 256 | ||
| 257 | if cnx_energy_db: |
|
| 258 | cnx_energy_db.close() |
|
| 259 | if cursor_energy_db: |
|
| 260 | cursor_energy_db.close() |
|
| 261 | ||
| 262 | if cnx_billing_db: |
|
| 263 | cnx_billing_db.close() |
|
| 264 | if cursor_billing_db: |
|
| 265 | cursor_billing_db.close() |
|
| 266 | print("go to sleep 300 seconds...") |
|
| 267 | time.sleep(300) |
|
| 268 | print("wake from sleep, and continue to work...") |
|
| 269 | # end of the outermost while loop |
|
| 270 | ||