Added the interface of carbon emission analysis report of meter
parent
eb6bd078dd
commit
0d9b67f93c
|
@ -38,6 +38,7 @@ from reports import fddspacefault
|
|||
from reports import fddstorefault
|
||||
from reports import fddtenantfault
|
||||
from reports import meterenergy
|
||||
from reports import metercarbon
|
||||
from reports import metercost
|
||||
from reports import meterrealtime
|
||||
from reports import metersubmetersbalance
|
||||
|
@ -557,6 +558,8 @@ api.add_route('/reports/fddtenantfault',
|
|||
fddtenantfault.Reporting())
|
||||
api.add_route('/reports/meterbatch',
|
||||
meterbatch.Reporting())
|
||||
api.add_route('/reports/metercarbon',
|
||||
metercarbon.Reporting())
|
||||
api.add_route('/reports/metercost',
|
||||
metercost.Reporting())
|
||||
api.add_route('/reports/meterenergy',
|
||||
|
|
|
@ -73,6 +73,14 @@ myems_reporting_db = {
|
|||
'password': config('MYEMS_REPORTING_DB_PASSWORD', default='!MyEMS1'),
|
||||
}
|
||||
|
||||
myems_carbon_db = {
|
||||
'host': config('MYEMS_CARBON_DB_HOST', default='127.0.0.1'),
|
||||
'port': config('MYEMS_CARBON_DB_PORT', default=3306, cast=int),
|
||||
'database': config('MYEMS_CARBON_DB_DATABASE', default='myems_carbon_db'),
|
||||
'user': config('MYEMS_CARBON_DB_USER', default='root'),
|
||||
'password': config('MYEMS_CARBON_DB_PASSWORD', default='!MyEMS1'),
|
||||
}
|
||||
|
||||
# indicated in how many minutes to calculate meter energy consumption
|
||||
# 30 for half hourly period
|
||||
# 60 for hourly period
|
||||
|
|
|
@ -0,0 +1,557 @@
|
|||
import base64
|
||||
import uuid
|
||||
import os
|
||||
import re
|
||||
from openpyxl.chart import LineChart, Reference, Series
|
||||
from openpyxl.styles import PatternFill, Border, Side, Alignment, Font
|
||||
from openpyxl.drawing.image import Image
|
||||
from openpyxl import Workbook
|
||||
from openpyxl.chart.label import DataLabelList
|
||||
import openpyxl.utils.cell as format_cell
|
||||
|
||||
|
||||
########################################################################################################################
|
||||
# PROCEDURES
|
||||
# Step 1: Validate the report data
|
||||
# Step 2: Generate excelexporters file
|
||||
# Step 3: Encode the excelexporters file to Base64
|
||||
########################################################################################################################
|
||||
|
||||
def export(report, name, reporting_start_datetime_local, reporting_end_datetime_local, period_type):
|
||||
####################################################################################################################
|
||||
# Step 1: Validate the report data
|
||||
####################################################################################################################
|
||||
if report is None:
|
||||
return None
|
||||
|
||||
if "reporting_period" not in report.keys() or \
|
||||
"values" not in report['reporting_period'].keys() or len(report['reporting_period']['values']) == 0:
|
||||
return None
|
||||
####################################################################################################################
|
||||
# Step 2: Generate excel file from the report data
|
||||
####################################################################################################################
|
||||
filename = generate_excel(report,
|
||||
name,
|
||||
reporting_start_datetime_local,
|
||||
reporting_end_datetime_local,
|
||||
period_type)
|
||||
####################################################################################################################
|
||||
# Step 3: Encode the excel file to Base64
|
||||
####################################################################################################################
|
||||
binary_file_data = b''
|
||||
try:
|
||||
with open(filename, 'rb') as binary_file:
|
||||
binary_file_data = binary_file.read()
|
||||
except IOError as ex:
|
||||
pass
|
||||
|
||||
# Base64 encode the bytes
|
||||
base64_encoded_data = base64.b64encode(binary_file_data)
|
||||
# get the Base64 encoded data using human-readable characters.
|
||||
base64_message = base64_encoded_data.decode('utf-8')
|
||||
# delete the file from server
|
||||
try:
|
||||
os.remove(filename)
|
||||
except NotImplementedError as ex:
|
||||
pass
|
||||
return base64_message
|
||||
|
||||
|
||||
def generate_excel(report, name, reporting_start_datetime_local, reporting_end_datetime_local, period_type):
|
||||
wb = Workbook()
|
||||
|
||||
# todo
|
||||
ws = wb.active
|
||||
ws.title = "MeterCarbonEmission"
|
||||
# Row height
|
||||
ws.row_dimensions[1].height = 102
|
||||
for i in range(2, 2000 + 1):
|
||||
ws.row_dimensions[i].height = 42
|
||||
|
||||
# Col width
|
||||
ws.column_dimensions['A'].width = 1.5
|
||||
|
||||
ws.column_dimensions['B'].width = 25.0
|
||||
|
||||
for i in range(ord('C'), ord('L')):
|
||||
ws.column_dimensions[chr(i)].width = 15.0
|
||||
|
||||
# Font
|
||||
name_font = Font(name='Arial', size=15, bold=True)
|
||||
title_font = Font(name='Arial', size=15, bold=True)
|
||||
|
||||
table_fill = PatternFill(fill_type='solid', fgColor='1F497D')
|
||||
f_border = Border(left=Side(border_style='medium', color='00000000'),
|
||||
right=Side(border_style='medium', color='00000000'),
|
||||
bottom=Side(border_style='medium', color='00000000'),
|
||||
top=Side(border_style='medium', color='00000000')
|
||||
)
|
||||
b_border = Border(
|
||||
bottom=Side(border_style='medium', color='00000000'),
|
||||
)
|
||||
|
||||
b_c_alignment = Alignment(vertical='bottom',
|
||||
horizontal='center',
|
||||
text_rotation=0,
|
||||
wrap_text=True,
|
||||
shrink_to_fit=False,
|
||||
indent=0)
|
||||
c_c_alignment = Alignment(vertical='center',
|
||||
horizontal='center',
|
||||
text_rotation=0,
|
||||
wrap_text=True,
|
||||
shrink_to_fit=False,
|
||||
indent=0)
|
||||
b_r_alignment = Alignment(vertical='bottom',
|
||||
horizontal='right',
|
||||
text_rotation=0,
|
||||
wrap_text=True,
|
||||
shrink_to_fit=False,
|
||||
indent=0)
|
||||
|
||||
# Img
|
||||
img = Image("excelexporters/myems.png")
|
||||
ws.add_image(img, 'A1')
|
||||
|
||||
# Title
|
||||
ws['B3'].alignment = b_r_alignment
|
||||
ws['B3'] = 'Name:'
|
||||
ws['C3'].border = b_border
|
||||
ws['C3'].alignment = b_c_alignment
|
||||
ws['C3'] = name
|
||||
|
||||
ws['D3'].alignment = b_r_alignment
|
||||
ws['D3'] = 'Period:'
|
||||
ws['E3'].border = b_border
|
||||
ws['E3'].alignment = b_c_alignment
|
||||
ws['E3'] = period_type
|
||||
|
||||
ws['B4'].alignment = b_r_alignment
|
||||
ws['B4'] = 'Reporting Start Datetime:'
|
||||
ws['C4'].border = b_border
|
||||
ws['C4'].alignment = b_c_alignment
|
||||
ws['C4'] = reporting_start_datetime_local
|
||||
|
||||
ws['D4'].alignment = b_r_alignment
|
||||
ws['D4'] = 'Reporting End Datetime:'
|
||||
ws['E4'].border = b_border
|
||||
ws['E4'].alignment = b_c_alignment
|
||||
ws['E4'] = reporting_end_datetime_local
|
||||
|
||||
if "reporting_period" not in report.keys() or \
|
||||
"values" not in report['reporting_period'].keys() or len(report['reporting_period']['values']) == 0:
|
||||
filename = str(uuid.uuid4()) + '.xlsx'
|
||||
wb.save(filename)
|
||||
|
||||
return filename
|
||||
|
||||
####################################################################################################################
|
||||
|
||||
has_cost_data_flag = True
|
||||
|
||||
if "values" not in report['reporting_period'].keys() or len(report['reporting_period']['values']) == 0:
|
||||
has_cost_data_flag = False
|
||||
|
||||
if has_cost_data_flag:
|
||||
ws['B6'].font = title_font
|
||||
ws['B6'] = name + 'Reporting Period Carbon Emission'
|
||||
|
||||
reporting_period_data = report['reporting_period']
|
||||
category = report['meter']['energy_category_name']
|
||||
ca_len = len(category)
|
||||
|
||||
ws.row_dimensions[7].height = 60
|
||||
ws['B7'].fill = table_fill
|
||||
ws['B7'].border = f_border
|
||||
|
||||
ws['B8'].font = title_font
|
||||
ws['B8'].alignment = c_c_alignment
|
||||
ws['B8'] = 'Carbon Emission'
|
||||
ws['B8'].border = f_border
|
||||
|
||||
ws['B9'].font = title_font
|
||||
ws['B9'].alignment = c_c_alignment
|
||||
ws['B9'] = 'Increment Rate'
|
||||
ws['B9'].border = f_border
|
||||
|
||||
col = 'B'
|
||||
|
||||
for i in range(0, ca_len):
|
||||
col = chr(ord('C') + i)
|
||||
|
||||
ws[col + '7'].fill = table_fill
|
||||
ws[col + '7'].font = name_font
|
||||
ws[col + '7'].alignment = c_c_alignment
|
||||
ws[col + '7'] = report['meter']['energy_category_name'] + " (" + report['meter']['unit_of_measure'] + ")"
|
||||
ws[col + '7'].border = f_border
|
||||
|
||||
ws[col + '8'].font = name_font
|
||||
ws[col + '8'].alignment = c_c_alignment
|
||||
ws[col + '8'] = round(reporting_period_data['total_in_category'], 2)
|
||||
ws[col + '8'].border = f_border
|
||||
|
||||
ws[col + '9'].font = name_font
|
||||
ws[col + '9'].alignment = c_c_alignment
|
||||
ws[col + '9'] = str(round(reporting_period_data['increment_rate'] * 100, 2)) + "%" \
|
||||
if reporting_period_data['increment_rate'] is not None else "-"
|
||||
ws[col + '9'].border = f_border
|
||||
|
||||
# TCE TCO2E
|
||||
end_col = col
|
||||
# TCE
|
||||
tce_col = chr(ord(end_col) + 1)
|
||||
ws[tce_col + '7'].fill = table_fill
|
||||
ws[tce_col + '7'].font = name_font
|
||||
ws[tce_col + '7'].alignment = c_c_alignment
|
||||
ws[tce_col + '7'] = 'Ton of Standard Coal (TCE)'
|
||||
ws[tce_col + '7'].border = f_border
|
||||
|
||||
ws[tce_col + '8'].font = name_font
|
||||
ws[tce_col + '8'].alignment = c_c_alignment
|
||||
ws[tce_col + '8'] = round(reporting_period_data['total_in_kgce'] / 1000, 2)
|
||||
ws[tce_col + '8'].border = f_border
|
||||
|
||||
ws[tce_col + '9'].font = name_font
|
||||
ws[tce_col + '9'].alignment = c_c_alignment
|
||||
ws[tce_col + '9'] = str(round(reporting_period_data['increment_rate'] * 100, 2)) + "%" \
|
||||
if reporting_period_data['increment_rate'] is not None else "-"
|
||||
ws[tce_col + '9'].border = f_border
|
||||
|
||||
# TCO2E
|
||||
tco2e_col = chr(ord(end_col) + 2)
|
||||
ws[tco2e_col + '7'].fill = table_fill
|
||||
ws[tco2e_col + '7'].font = name_font
|
||||
ws[tco2e_col + '7'].alignment = c_c_alignment
|
||||
ws[tco2e_col + '7'] = 'Ton of Carbon Dioxide Emissions (TCO2E)'
|
||||
ws[tco2e_col + '7'].border = f_border
|
||||
|
||||
ws[tco2e_col + '8'].font = name_font
|
||||
ws[tco2e_col + '8'].alignment = c_c_alignment
|
||||
ws[tco2e_col + '8'] = round(reporting_period_data['total_in_kgco2e'] / 1000, 2)
|
||||
ws[tco2e_col + '8'].border = f_border
|
||||
|
||||
ws[tco2e_col + '9'].font = name_font
|
||||
ws[tco2e_col + '9'].alignment = c_c_alignment
|
||||
ws[tco2e_col + '9'] = str(round(reporting_period_data['increment_rate'] * 100, 2)) + "%" \
|
||||
if reporting_period_data['increment_rate'] is not None else "-"
|
||||
ws[tco2e_col + '9'].border = f_border
|
||||
|
||||
else:
|
||||
for i in range(6, 9 + 1):
|
||||
ws.rows_dimensions[i].height = 0.1
|
||||
|
||||
####################################################################################################################
|
||||
|
||||
has_cost_datail_flag = True
|
||||
reporting_period_data = report['reporting_period']
|
||||
category = report['meter']['energy_category_name']
|
||||
ca_len = len(category)
|
||||
times = reporting_period_data['timestamps']
|
||||
parameters_names_len = len(report['parameters']['names'])
|
||||
parameters_data = report['parameters']
|
||||
parameters_parameters_datas_len = 0
|
||||
for i in range(0, parameters_names_len):
|
||||
if len(parameters_data['timestamps'][i]) == 0:
|
||||
continue
|
||||
parameters_parameters_datas_len += 1
|
||||
|
||||
if "values" not in reporting_period_data.keys() or len(reporting_period_data['values']) == 0:
|
||||
has_cost_datail_flag = False
|
||||
|
||||
if has_cost_datail_flag:
|
||||
start_detail_data_row_number = 13 + (parameters_parameters_datas_len + ca_len) * 6
|
||||
|
||||
ws['B11'].font = title_font
|
||||
ws['B11'] = name + 'Detailed Data'
|
||||
|
||||
ws.row_dimensions[start_detail_data_row_number].height = 60
|
||||
ws['B' + str(start_detail_data_row_number)].fill = table_fill
|
||||
ws['B' + str(start_detail_data_row_number)].font = title_font
|
||||
ws['B' + str(start_detail_data_row_number)].border = f_border
|
||||
ws['B' + str(start_detail_data_row_number)].alignment = c_c_alignment
|
||||
ws['B' + str(start_detail_data_row_number)] = 'Datetime'
|
||||
time = times
|
||||
has_data = False
|
||||
max_row = 0
|
||||
if len(time) > 0:
|
||||
has_data = True
|
||||
max_row = start_detail_data_row_number + len(time)
|
||||
|
||||
if has_data:
|
||||
|
||||
end_data_row_number = start_detail_data_row_number
|
||||
|
||||
for i in range(0, len(time)):
|
||||
col = 'B'
|
||||
end_data_row_number += 1
|
||||
row = str(end_data_row_number)
|
||||
|
||||
ws[col + row].font = title_font
|
||||
ws[col + row].alignment = c_c_alignment
|
||||
ws[col + row] = time[i]
|
||||
ws[col + row].border = f_border
|
||||
|
||||
ws['B' + str(end_data_row_number + 1)].font = title_font
|
||||
ws['B' + str(end_data_row_number + 1)].alignment = c_c_alignment
|
||||
ws['B' + str(end_data_row_number + 1)] = 'Total'
|
||||
ws['B' + str(end_data_row_number + 1)].border = f_border
|
||||
|
||||
for i in range(0, ca_len):
|
||||
|
||||
col = chr(ord('C') + i)
|
||||
|
||||
ws[col + str(start_detail_data_row_number)].fill = table_fill
|
||||
ws[col + str(start_detail_data_row_number)].font = title_font
|
||||
ws[col + str(start_detail_data_row_number)].alignment = c_c_alignment
|
||||
ws[col + str(start_detail_data_row_number)] = \
|
||||
report['meter']['energy_category_name']+" (" + report['meter']['unit_of_measure'] + ")"
|
||||
ws[col + str(start_detail_data_row_number)].border = f_border
|
||||
|
||||
time = times
|
||||
time_len = len(time)
|
||||
|
||||
for j in range(0, time_len):
|
||||
row = str(start_detail_data_row_number + 1 + j)
|
||||
|
||||
ws[col + row].font = title_font
|
||||
ws[col + row].alignment = c_c_alignment
|
||||
ws[col + row] = round(reporting_period_data['values'][j], 2)
|
||||
ws[col + row].border = f_border
|
||||
|
||||
ws[col + str(end_data_row_number + 1)].font = title_font
|
||||
ws[col + str(end_data_row_number + 1)].alignment = c_c_alignment
|
||||
ws[col + str(end_data_row_number + 1)] = round(reporting_period_data['total_in_category'], 2)
|
||||
ws[col + str(end_data_row_number + 1)].border = f_border
|
||||
|
||||
line = LineChart()
|
||||
line.title = 'Reporting Period Costs - ' + report['meter']['energy_category_name'] + \
|
||||
" (" + report['meter']['unit_of_measure'] + ")"
|
||||
line_data = Reference(ws, min_col=3, min_row=start_detail_data_row_number, max_row=max_row)
|
||||
line.series.append(Series(line_data, title_from_data=True))
|
||||
labels = Reference(ws, min_col=2, min_row=start_detail_data_row_number + 1, max_row=max_row)
|
||||
line.set_categories(labels)
|
||||
line_data = line.series[0]
|
||||
line_data.marker.symbol = "circle"
|
||||
line_data.smooth = True
|
||||
line.x_axis.crosses = 'min'
|
||||
line.dLbls = DataLabelList()
|
||||
line.dLbls.dLblPos = 't'
|
||||
line.dLbls.showVal = True
|
||||
line.height = 8.25
|
||||
line.width = 24
|
||||
ws.add_chart(line, "B12")
|
||||
else:
|
||||
for i in range(11, 43 + 1):
|
||||
ws.row_dimensions[i].height = 0.0
|
||||
|
||||
####################################################################################################################
|
||||
has_parameters_names_and_timestamps_and_values_data = True
|
||||
# 12 is the starting line number of the last line chart in the report period
|
||||
time_len = len(reporting_period_data['timestamps'])
|
||||
current_sheet_parameters_row_number = 12 + ca_len * 6
|
||||
if 'parameters' not in report.keys() or \
|
||||
report['parameters'] is None or \
|
||||
'names' not in report['parameters'].keys() or \
|
||||
report['parameters']['names'] is None or \
|
||||
len(report['parameters']['names']) == 0 or \
|
||||
'timestamps' not in report['parameters'].keys() or \
|
||||
report['parameters']['timestamps'] is None or \
|
||||
len(report['parameters']['timestamps']) == 0 or \
|
||||
'values' not in report['parameters'].keys() or \
|
||||
report['parameters']['values'] is None or \
|
||||
len(report['parameters']['values']) == 0 or \
|
||||
timestamps_data_all_equal_0(report['parameters']['timestamps']):
|
||||
has_parameters_names_and_timestamps_and_values_data = False
|
||||
if has_parameters_names_and_timestamps_and_values_data:
|
||||
|
||||
################################################################################################################
|
||||
# new worksheet
|
||||
################################################################################################################
|
||||
|
||||
parameters_data = report['parameters']
|
||||
|
||||
parameters_names_len = len(parameters_data['names'])
|
||||
|
||||
file_name = (re.sub(r'[^A-Z]', '', ws.title))+'_'
|
||||
parameters_ws = wb.create_sheet(file_name + 'Parameters')
|
||||
|
||||
parameters_timestamps_data_max_len = \
|
||||
get_parameters_timestamps_lists_max_len(list(parameters_data['timestamps']))
|
||||
|
||||
# Row height
|
||||
parameters_ws.row_dimensions[1].height = 102
|
||||
for i in range(2, 7 + 1):
|
||||
parameters_ws.row_dimensions[i].height = 42
|
||||
|
||||
for i in range(8, parameters_timestamps_data_max_len + 10):
|
||||
parameters_ws.row_dimensions[i].height = 60
|
||||
|
||||
# Col width
|
||||
parameters_ws.column_dimensions['A'].width = 1.5
|
||||
|
||||
parameters_ws.column_dimensions['B'].width = 25.0
|
||||
|
||||
for i in range(3, 12 + parameters_names_len * 3):
|
||||
parameters_ws.column_dimensions[format_cell.get_column_letter(i)].width = 15.0
|
||||
|
||||
# Img
|
||||
img = Image("excelexporters/myems.png")
|
||||
parameters_ws.add_image(img, 'A1')
|
||||
|
||||
# Title
|
||||
parameters_ws['B3'].alignment = b_r_alignment
|
||||
parameters_ws['B3'] = 'Name:'
|
||||
parameters_ws['C3'].border = b_border
|
||||
parameters_ws['C3'].alignment = b_c_alignment
|
||||
parameters_ws['C3'] = name
|
||||
|
||||
parameters_ws['D3'].alignment = b_r_alignment
|
||||
parameters_ws['D3'] = 'Period:'
|
||||
parameters_ws['E3'].border = b_border
|
||||
parameters_ws['E3'].alignment = b_c_alignment
|
||||
parameters_ws['E3'] = period_type
|
||||
|
||||
parameters_ws['B4'].alignment = b_r_alignment
|
||||
parameters_ws['B4'] = 'Reporting Start Datetime:'
|
||||
parameters_ws['C4'].border = b_border
|
||||
parameters_ws['C4'].alignment = b_c_alignment
|
||||
parameters_ws['C4'] = reporting_start_datetime_local
|
||||
|
||||
parameters_ws['D4'].alignment = b_r_alignment
|
||||
parameters_ws['D4'] = 'Reporting End Datetime:'
|
||||
parameters_ws['E4'].border = b_border
|
||||
parameters_ws['E4'].alignment = b_c_alignment
|
||||
parameters_ws['E4'] = reporting_end_datetime_local
|
||||
|
||||
parameters_ws_current_row_number = 6
|
||||
|
||||
parameters_ws['B' + str(parameters_ws_current_row_number)].font = title_font
|
||||
parameters_ws['B' + str(parameters_ws_current_row_number)] = name + ' ' + 'Parameters'
|
||||
|
||||
parameters_ws_current_row_number += 1
|
||||
|
||||
parameters_table_start_row_number = parameters_ws_current_row_number
|
||||
|
||||
parameters_ws.row_dimensions[parameters_ws_current_row_number].height = 80
|
||||
|
||||
parameters_ws_current_row_number += 1
|
||||
|
||||
table_current_col_number = 2
|
||||
|
||||
for i in range(0, parameters_names_len):
|
||||
|
||||
if len(parameters_data['timestamps'][i]) == 0:
|
||||
continue
|
||||
|
||||
col = format_cell.get_column_letter(table_current_col_number)
|
||||
|
||||
parameters_ws[col + str(parameters_ws_current_row_number - 1)].fill = table_fill
|
||||
parameters_ws[col + str(parameters_ws_current_row_number - 1)].border = f_border
|
||||
|
||||
col = format_cell.get_column_letter(table_current_col_number + 1)
|
||||
|
||||
parameters_ws[col + str(parameters_ws_current_row_number - 1)].fill = table_fill
|
||||
parameters_ws[col + str(parameters_ws_current_row_number - 1)].border = f_border
|
||||
parameters_ws[col + str(parameters_ws_current_row_number - 1)].font = name_font
|
||||
parameters_ws[col + str(parameters_ws_current_row_number - 1)].alignment = c_c_alignment
|
||||
parameters_ws[col + str(parameters_ws_current_row_number - 1)] = parameters_data['names'][i]
|
||||
|
||||
table_current_row_number = parameters_ws_current_row_number
|
||||
|
||||
for j, value in enumerate(list(parameters_data['timestamps'][i])):
|
||||
col = format_cell.get_column_letter(table_current_col_number)
|
||||
|
||||
parameters_ws[col + str(table_current_row_number)].border = f_border
|
||||
parameters_ws[col + str(table_current_row_number)].font = title_font
|
||||
parameters_ws[col + str(table_current_row_number)].alignment = c_c_alignment
|
||||
parameters_ws[col + str(table_current_row_number)] = value
|
||||
|
||||
col = format_cell.get_column_letter(table_current_col_number + 1)
|
||||
|
||||
parameters_ws[col + str(table_current_row_number)].border = f_border
|
||||
parameters_ws[col + str(table_current_row_number)].font = title_font
|
||||
parameters_ws[col + str(table_current_row_number)].alignment = c_c_alignment
|
||||
parameters_ws[col + str(table_current_row_number)] = round(parameters_data['values'][i][j], 2)
|
||||
|
||||
table_current_row_number += 1
|
||||
|
||||
table_current_col_number = table_current_col_number + 3
|
||||
|
||||
################################################################################################################
|
||||
# parameters chart and parameters table
|
||||
################################################################################################################
|
||||
|
||||
ws['B' + str(current_sheet_parameters_row_number)].font = title_font
|
||||
ws['B' + str(current_sheet_parameters_row_number)] = name + ' ' + 'Parameters'
|
||||
|
||||
current_sheet_parameters_row_number += 1
|
||||
|
||||
chart_start_row_number = current_sheet_parameters_row_number
|
||||
|
||||
col_index = 0
|
||||
|
||||
for i in range(0, parameters_names_len):
|
||||
|
||||
if len(parameters_data['timestamps'][i]) == 0:
|
||||
continue
|
||||
|
||||
line = LineChart()
|
||||
data_col = 3 + col_index * 3
|
||||
labels_col = 2 + col_index * 3
|
||||
col_index += 1
|
||||
line.title = 'Parameters - ' + \
|
||||
parameters_ws.cell(row=parameters_table_start_row_number, column=data_col).value
|
||||
labels = Reference(parameters_ws, min_col=labels_col, min_row=parameters_table_start_row_number + 1,
|
||||
max_row=(len(parameters_data['timestamps'][i]) + parameters_table_start_row_number))
|
||||
line_data = Reference(parameters_ws, min_col=data_col, min_row=parameters_table_start_row_number,
|
||||
max_row=(len(parameters_data['timestamps'][i]) + parameters_table_start_row_number))
|
||||
line.add_data(line_data, titles_from_data=True)
|
||||
line.set_categories(labels)
|
||||
line_data = line.series[0]
|
||||
line_data.marker.symbol = "circle"
|
||||
line_data.smooth = True
|
||||
line.x_axis.crosses = 'min'
|
||||
line.height = 8.25
|
||||
line.width = 24
|
||||
line.dLbls = DataLabelList()
|
||||
line.dLbls.dLblPos = 't'
|
||||
line.dLbls.showVal = False
|
||||
line.dLbls.showPercent = False
|
||||
chart_col = 'B'
|
||||
chart_cell = chart_col + str(chart_start_row_number)
|
||||
chart_start_row_number += 6
|
||||
ws.add_chart(line, chart_cell)
|
||||
|
||||
current_sheet_parameters_row_number = chart_start_row_number
|
||||
|
||||
current_sheet_parameters_row_number += 1
|
||||
|
||||
filename = str(uuid.uuid4()) + '.xlsx'
|
||||
wb.save(filename)
|
||||
|
||||
return filename
|
||||
|
||||
|
||||
def timestamps_data_all_equal_0(lists):
|
||||
for i, value in enumerate(list(lists)):
|
||||
if len(value) > 0:
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
|
||||
def get_parameters_timestamps_lists_max_len(parameters_timestamps_lists):
|
||||
max_len = 0
|
||||
for i, value in enumerate(list(parameters_timestamps_lists)):
|
||||
if len(value) > max_len:
|
||||
max_len = len(value)
|
||||
|
||||
return max_len
|
||||
|
||||
|
||||
def timestamps_data_not_equal_0(lists):
|
||||
number = 0
|
||||
for i, value in enumerate(list(lists)):
|
||||
if len(value) > 0:
|
||||
number += 1
|
||||
return number
|
|
@ -0,0 +1,495 @@
|
|||
import re
|
||||
import falcon
|
||||
import simplejson as json
|
||||
import mysql.connector
|
||||
import config
|
||||
from datetime import datetime, timedelta, timezone
|
||||
from core import utilities
|
||||
from decimal import Decimal
|
||||
import excelexporters.metercost
|
||||
|
||||
|
||||
class Reporting:
|
||||
@staticmethod
|
||||
def __init__():
|
||||
""""Initializes Reporting"""
|
||||
pass
|
||||
|
||||
@staticmethod
|
||||
def on_options(req, resp):
|
||||
resp.status = falcon.HTTP_200
|
||||
|
||||
####################################################################################################################
|
||||
# PROCEDURES
|
||||
# Step 1: valid parameters
|
||||
# Step 2: query the meter and carbon
|
||||
# Step 3: query associated points
|
||||
# Step 4: query base period carbon consumption
|
||||
# Step 5: query base period carbon Emission
|
||||
# Step 6: query reporting period energy consumption
|
||||
# Step 7: query reporting period energy cost
|
||||
# Step 8: query tariff data
|
||||
# Step 9: query associated points data
|
||||
# Step 10: construct the report
|
||||
####################################################################################################################
|
||||
@staticmethod
|
||||
def on_get(req, resp):
|
||||
print(req.params)
|
||||
meter_id = req.params.get('meterid')
|
||||
meter_uuid = req.params.get('meteruuid')
|
||||
period_type = req.params.get('periodtype')
|
||||
base_period_start_datetime_local = req.params.get('baseperiodstartdatetime')
|
||||
base_period_end_datetime_local = req.params.get('baseperiodenddatetime')
|
||||
reporting_period_start_datetime_local = req.params.get('reportingperiodstartdatetime')
|
||||
reporting_period_end_datetime_local = req.params.get('reportingperiodenddatetime')
|
||||
|
||||
################################################################################################################
|
||||
# Step 1: valid parameters
|
||||
################################################################################################################
|
||||
if meter_id is None and meter_uuid is None:
|
||||
raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST', description='API.INVALID_METER_ID')
|
||||
|
||||
if meter_id is not None:
|
||||
meter_id = str.strip(meter_id)
|
||||
if not meter_id.isdigit() or int(meter_id) <= 0:
|
||||
raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST', description='API.INVALID_METER_ID')
|
||||
|
||||
if meter_uuid is not None:
|
||||
meter_uuid = str.strip(meter_uuid)
|
||||
regex = re.compile('^[a-f0-9]{8}-?[a-f0-9]{4}-?4[a-f0-9]{3}-?[89ab][a-f0-9]{3}-?[a-f0-9]{12}\Z', re.I)
|
||||
match = regex.match(meter_uuid)
|
||||
if not bool(match):
|
||||
raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST', description='API.INVALID_METER_UUID')
|
||||
|
||||
if period_type is None:
|
||||
raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST', description='API.INVALID_PERIOD_TYPE')
|
||||
else:
|
||||
period_type = str.strip(period_type)
|
||||
if period_type not in ['hourly', 'daily', 'weekly', 'monthly', 'yearly']:
|
||||
raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST', description='API.INVALID_PERIOD_TYPE')
|
||||
|
||||
timezone_offset = int(config.utc_offset[1:3]) * 60 + int(config.utc_offset[4:6])
|
||||
if config.utc_offset[0] == '-':
|
||||
timezone_offset = -timezone_offset
|
||||
|
||||
base_start_datetime_utc = None
|
||||
if base_period_start_datetime_local is not None and len(str.strip(base_period_start_datetime_local)) > 0:
|
||||
base_period_start_datetime_local = str.strip(base_period_start_datetime_local)
|
||||
try:
|
||||
base_start_datetime_utc = datetime.strptime(base_period_start_datetime_local, '%Y-%m-%dT%H:%M:%S')
|
||||
except ValueError:
|
||||
raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST',
|
||||
description="API.INVALID_BASE_PERIOD_START_DATETIME")
|
||||
base_start_datetime_utc = base_start_datetime_utc.replace(tzinfo=timezone.utc) - \
|
||||
timedelta(minutes=timezone_offset)
|
||||
|
||||
base_end_datetime_utc = None
|
||||
if base_period_end_datetime_local is not None and len(str.strip(base_period_end_datetime_local)) > 0:
|
||||
base_period_end_datetime_local = str.strip(base_period_end_datetime_local)
|
||||
try:
|
||||
base_end_datetime_utc = datetime.strptime(base_period_end_datetime_local, '%Y-%m-%dT%H:%M:%S')
|
||||
except ValueError:
|
||||
raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST',
|
||||
description="API.INVALID_BASE_PERIOD_END_DATETIME")
|
||||
base_end_datetime_utc = base_end_datetime_utc.replace(tzinfo=timezone.utc) - \
|
||||
timedelta(minutes=timezone_offset)
|
||||
|
||||
if base_start_datetime_utc is not None and base_end_datetime_utc is not None and \
|
||||
base_start_datetime_utc >= base_end_datetime_utc:
|
||||
raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST',
|
||||
description='API.INVALID_BASE_PERIOD_END_DATETIME')
|
||||
|
||||
if reporting_period_start_datetime_local is None:
|
||||
raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST',
|
||||
description="API.INVALID_REPORTING_PERIOD_START_DATETIME")
|
||||
else:
|
||||
reporting_period_start_datetime_local = str.strip(reporting_period_start_datetime_local)
|
||||
try:
|
||||
reporting_start_datetime_utc = datetime.strptime(reporting_period_start_datetime_local,
|
||||
'%Y-%m-%dT%H:%M:%S')
|
||||
except ValueError:
|
||||
raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST',
|
||||
description="API.INVALID_REPORTING_PERIOD_START_DATETIME")
|
||||
reporting_start_datetime_utc = reporting_start_datetime_utc.replace(tzinfo=timezone.utc) - \
|
||||
timedelta(minutes=timezone_offset)
|
||||
|
||||
if reporting_period_end_datetime_local is None:
|
||||
raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST',
|
||||
description="API.INVALID_REPORTING_PERIOD_END_DATETIME")
|
||||
else:
|
||||
reporting_period_end_datetime_local = str.strip(reporting_period_end_datetime_local)
|
||||
try:
|
||||
reporting_end_datetime_utc = datetime.strptime(reporting_period_end_datetime_local,
|
||||
'%Y-%m-%dT%H:%M:%S')
|
||||
except ValueError:
|
||||
raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST',
|
||||
description="API.INVALID_REPORTING_PERIOD_END_DATETIME")
|
||||
reporting_end_datetime_utc = reporting_end_datetime_utc.replace(tzinfo=timezone.utc) - \
|
||||
timedelta(minutes=timezone_offset)
|
||||
|
||||
if reporting_start_datetime_utc >= reporting_end_datetime_utc:
|
||||
raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST',
|
||||
description='API.INVALID_REPORTING_PERIOD_END_DATETIME')
|
||||
|
||||
################################################################################################################
|
||||
# Step 2: query the meter and carbon
|
||||
################################################################################################################
|
||||
cnx_system = mysql.connector.connect(**config.myems_system_db)
|
||||
cursor_system = cnx_system.cursor()
|
||||
|
||||
cnx_carbon = mysql.connector.connect(**config.myems_carbon_db)
|
||||
cursor_carbon = cnx_carbon.cursor()
|
||||
|
||||
cnx_billing = mysql.connector.connect(**config.myems_billing_db)
|
||||
cursor_billing = cnx_billing.cursor()
|
||||
|
||||
cnx_historical = mysql.connector.connect(**config.myems_historical_db)
|
||||
cursor_historical = cnx_historical.cursor()
|
||||
if meter_id is not None:
|
||||
cursor_system.execute(" SELECT m.id, m.name, m.cost_center_id, m.energy_category_id, "
|
||||
" ec.name, ec.unit_of_measure, ec.kgce, ec.kgco2e "
|
||||
" FROM tbl_meters m, tbl_energy_categories ec "
|
||||
" WHERE m.id = %s AND m.energy_category_id = ec.id ", (meter_id,))
|
||||
row_meter = cursor_system.fetchone()
|
||||
elif meter_uuid is not None:
|
||||
cursor_system.execute(" SELECT m.id, m.name, m.cost_center_id, m.energy_category_id, "
|
||||
" ec.name, ec.unit_of_measure, ec.kgce, ec.kgco2e "
|
||||
" FROM tbl_meters m, tbl_energy_categories ec "
|
||||
" WHERE m.uuid = %s AND m.energy_category_id = ec.id ", (meter_uuid,))
|
||||
row_meter = cursor_system.fetchone()
|
||||
if row_meter is None:
|
||||
if cursor_system:
|
||||
cursor_system.close()
|
||||
if cnx_system:
|
||||
cnx_system.disconnect()
|
||||
|
||||
if cursor_carbon:
|
||||
cursor_carbon.close()
|
||||
if cnx_carbon:
|
||||
cnx_carbon.disconnect()
|
||||
|
||||
if cursor_billing:
|
||||
cursor_billing.close()
|
||||
if cnx_billing:
|
||||
cnx_billing.disconnect()
|
||||
|
||||
if cursor_historical:
|
||||
cursor_historical.close()
|
||||
if cnx_historical:
|
||||
cnx_historical.disconnect()
|
||||
raise falcon.HTTPError(falcon.HTTP_404, title='API.NOT_FOUND', description='API.METER_NOT_FOUND')
|
||||
if meter_id is not None and int(meter_id) != int(row_meter[0]):
|
||||
raise falcon.HTTPError(falcon.HTTP_404, title='API.NOT_FOUND', description='API.METER_NOT_FOUND')
|
||||
meter = dict()
|
||||
meter['id'] = row_meter[0]
|
||||
meter['name'] = row_meter[1]
|
||||
meter['cost_center_id'] = row_meter[2]
|
||||
meter['energy_category_id'] = row_meter[3]
|
||||
meter['energy_category_name'] = row_meter[4]
|
||||
meter['unit_of_measure'] = config.currency_unit
|
||||
meter['kgce'] = row_meter[6]
|
||||
meter['kgco2e'] = row_meter[7]
|
||||
|
||||
################################################################################################################
|
||||
# Step 3: query associated points
|
||||
################################################################################################################
|
||||
point_list = list()
|
||||
cursor_system.execute(" SELECT p.id, p.name, p.units, p.object_type "
|
||||
" FROM tbl_meters m, tbl_meters_points mp, tbl_points p "
|
||||
" WHERE m.id = %s AND m.id = mp.meter_id AND mp.point_id = p.id "
|
||||
" ORDER BY p.id ", (meter['id'],))
|
||||
rows_points = cursor_system.fetchall()
|
||||
if rows_points is not None and len(rows_points) > 0:
|
||||
for row in rows_points:
|
||||
point_list.append({"id": row[0], "name": row[1], "units": row[2], "object_type": row[3]})
|
||||
|
||||
################################################################################################################
|
||||
# Step 4: query base period carbon consumption
|
||||
################################################################################################################
|
||||
query = (" SELECT start_datetime_utc, actual_value "
|
||||
" FROM tbl_meter_hourly "
|
||||
" WHERE meter_id = %s "
|
||||
" AND start_datetime_utc >= %s "
|
||||
" AND start_datetime_utc < %s "
|
||||
" ORDER BY start_datetime_utc ")
|
||||
cursor_carbon.execute(query, (meter['id'], base_start_datetime_utc, base_end_datetime_utc))
|
||||
rows_meter_hourly = cursor_carbon.fetchall()
|
||||
|
||||
rows_meter_periodically = utilities.aggregate_hourly_data_by_period(rows_meter_hourly,
|
||||
base_start_datetime_utc,
|
||||
base_end_datetime_utc,
|
||||
period_type)
|
||||
base = dict()
|
||||
base['timestamps'] = list()
|
||||
base['values'] = list()
|
||||
base['total_in_category'] = Decimal(0.0)
|
||||
base['total_in_kgce'] = Decimal(0.0)
|
||||
base['total_in_kgco2e'] = Decimal(0.0)
|
||||
|
||||
for row_meter_periodically in rows_meter_periodically:
|
||||
current_datetime_local = row_meter_periodically[0].replace(tzinfo=timezone.utc) + \
|
||||
timedelta(minutes=timezone_offset)
|
||||
if period_type == 'hourly':
|
||||
current_datetime = current_datetime_local.strftime('%Y-%m-%dT%H:%M:%S')
|
||||
elif period_type == 'daily':
|
||||
current_datetime = current_datetime_local.strftime('%Y-%m-%d')
|
||||
elif period_type == 'weekly':
|
||||
current_datetime = current_datetime_local.strftime('%Y-%m-%d')
|
||||
elif period_type == 'monthly':
|
||||
current_datetime = current_datetime_local.strftime('%Y-%m')
|
||||
elif period_type == 'yearly':
|
||||
current_datetime = current_datetime_local.strftime('%Y')
|
||||
|
||||
actual_value = Decimal(0.0) if row_meter_periodically[1] is None \
|
||||
else row_meter_periodically[1]
|
||||
base['timestamps'].append(current_datetime)
|
||||
base['total_in_kgce'] += actual_value * meter['kgce']
|
||||
base['total_in_kgco2e'] += actual_value * meter['kgco2e']
|
||||
|
||||
################################################################################################################
|
||||
# Step 5: query base period Carbon Emission
|
||||
################################################################################################################
|
||||
query = (" SELECT start_datetime_utc, actual_value "
|
||||
" FROM tbl_meter_hourly "
|
||||
" WHERE meter_id = %s "
|
||||
" AND start_datetime_utc >= %s "
|
||||
" AND start_datetime_utc < %s "
|
||||
" ORDER BY start_datetime_utc ")
|
||||
cursor_billing.execute(query, (meter['id'], base_start_datetime_utc, base_end_datetime_utc))
|
||||
rows_meter_hourly = cursor_billing.fetchall()
|
||||
|
||||
rows_meter_periodically = utilities.aggregate_hourly_data_by_period(rows_meter_hourly,
|
||||
base_start_datetime_utc,
|
||||
base_end_datetime_utc,
|
||||
period_type)
|
||||
|
||||
base['values'] = list()
|
||||
base['total_in_category'] = Decimal(0.0)
|
||||
|
||||
for row_meter_periodically in rows_meter_periodically:
|
||||
actual_value = Decimal(0.0) if row_meter_periodically[1] is None \
|
||||
else row_meter_periodically[1]
|
||||
base['values'].append(actual_value)
|
||||
base['total_in_category'] += actual_value
|
||||
|
||||
################################################################################################################
|
||||
# Step 6: query reporting period carbon consumption
|
||||
################################################################################################################
|
||||
query = (" SELECT start_datetime_utc, actual_value "
|
||||
" FROM tbl_meter_hourly "
|
||||
" WHERE meter_id = %s "
|
||||
" AND start_datetime_utc >= %s "
|
||||
" AND start_datetime_utc < %s "
|
||||
" ORDER BY start_datetime_utc ")
|
||||
cursor_carbon.execute(query, (meter['id'], reporting_start_datetime_utc, reporting_end_datetime_utc))
|
||||
rows_meter_hourly = cursor_carbon.fetchall()
|
||||
|
||||
rows_meter_periodically = utilities.aggregate_hourly_data_by_period(rows_meter_hourly,
|
||||
reporting_start_datetime_utc,
|
||||
reporting_end_datetime_utc,
|
||||
period_type)
|
||||
reporting = dict()
|
||||
reporting['timestamps'] = list()
|
||||
reporting['values'] = list()
|
||||
reporting['total_in_category'] = Decimal(0.0)
|
||||
reporting['total_in_kgce'] = Decimal(0.0)
|
||||
reporting['total_in_kgco2e'] = Decimal(0.0)
|
||||
|
||||
for row_meter_periodically in rows_meter_periodically:
|
||||
current_datetime_local = row_meter_periodically[0].replace(tzinfo=timezone.utc) + \
|
||||
timedelta(minutes=timezone_offset)
|
||||
if period_type == 'hourly':
|
||||
current_datetime = current_datetime_local.strftime('%Y-%m-%dT%H:%M:%S')
|
||||
elif period_type == 'daily':
|
||||
current_datetime = current_datetime_local.strftime('%Y-%m-%d')
|
||||
elif period_type == 'weekly':
|
||||
current_datetime = current_datetime_local.strftime('%Y-%m-%d')
|
||||
elif period_type == 'monthly':
|
||||
current_datetime = current_datetime_local.strftime('%Y-%m')
|
||||
elif period_type == 'yearly':
|
||||
current_datetime = current_datetime_local.strftime('%Y')
|
||||
|
||||
actual_value = Decimal(0.0) if row_meter_periodically[1] is None \
|
||||
else row_meter_periodically[1]
|
||||
|
||||
reporting['timestamps'].append(current_datetime)
|
||||
reporting['total_in_kgce'] += actual_value * meter['kgce']
|
||||
reporting['total_in_kgco2e'] += actual_value * meter['kgco2e']
|
||||
|
||||
################################################################################################################
|
||||
# Step 7: query reporting period carbon cost
|
||||
################################################################################################################
|
||||
query = (" SELECT start_datetime_utc, actual_value "
|
||||
" FROM tbl_meter_hourly "
|
||||
" WHERE meter_id = %s "
|
||||
" AND start_datetime_utc >= %s "
|
||||
" AND start_datetime_utc < %s "
|
||||
" ORDER BY start_datetime_utc ")
|
||||
cursor_billing.execute(query, (meter['id'], reporting_start_datetime_utc, reporting_end_datetime_utc))
|
||||
rows_meter_hourly = cursor_billing.fetchall()
|
||||
|
||||
rows_meter_periodically = utilities.aggregate_hourly_data_by_period(rows_meter_hourly,
|
||||
reporting_start_datetime_utc,
|
||||
reporting_end_datetime_utc,
|
||||
period_type)
|
||||
|
||||
for row_meter_periodically in rows_meter_periodically:
|
||||
actual_value = Decimal(0.0) if row_meter_periodically[1] is None \
|
||||
else row_meter_periodically[1]
|
||||
|
||||
reporting['values'].append(actual_value)
|
||||
reporting['total_in_category'] += actual_value
|
||||
|
||||
################################################################################################################
|
||||
# Step 8: query tariff data
|
||||
################################################################################################################
|
||||
parameters_data = dict()
|
||||
parameters_data['names'] = list()
|
||||
parameters_data['timestamps'] = list()
|
||||
parameters_data['values'] = list()
|
||||
|
||||
tariff_dict = utilities.get_energy_category_tariffs(meter['cost_center_id'],
|
||||
meter['energy_category_id'],
|
||||
reporting_start_datetime_utc,
|
||||
reporting_end_datetime_utc)
|
||||
tariff_timestamp_list = list()
|
||||
tariff_value_list = list()
|
||||
for k, v in tariff_dict.items():
|
||||
# convert k from utc to local
|
||||
k = k + timedelta(minutes=timezone_offset)
|
||||
tariff_timestamp_list.append(k.isoformat()[0:19])
|
||||
tariff_value_list.append(v)
|
||||
|
||||
parameters_data['names'].append('TARIFF-' + meter['energy_category_name'])
|
||||
parameters_data['timestamps'].append(tariff_timestamp_list)
|
||||
parameters_data['values'].append(tariff_value_list)
|
||||
|
||||
################################################################################################################
|
||||
# Step 9: query associated points data
|
||||
################################################################################################################
|
||||
for point in point_list:
|
||||
point_values = []
|
||||
point_timestamps = []
|
||||
if point['object_type'] == 'ANALOG_VALUE':
|
||||
query = (" SELECT utc_date_time, actual_value "
|
||||
" FROM tbl_analog_value "
|
||||
" WHERE point_id = %s "
|
||||
" AND utc_date_time BETWEEN %s AND %s "
|
||||
" ORDER BY utc_date_time ")
|
||||
cursor_historical.execute(query, (point['id'],
|
||||
reporting_start_datetime_utc,
|
||||
reporting_end_datetime_utc))
|
||||
rows = cursor_historical.fetchall()
|
||||
|
||||
if rows is not None and len(rows) > 0:
|
||||
for row in rows:
|
||||
current_datetime_local = row[0].replace(tzinfo=timezone.utc) + \
|
||||
timedelta(minutes=timezone_offset)
|
||||
current_datetime = current_datetime_local.strftime('%Y-%m-%dT%H:%M:%S')
|
||||
point_timestamps.append(current_datetime)
|
||||
point_values.append(row[1])
|
||||
|
||||
elif point['object_type'] == 'ENERGY_VALUE':
|
||||
query = (" SELECT utc_date_time, actual_value "
|
||||
" FROM tbl_energy_value "
|
||||
" WHERE point_id = %s "
|
||||
" AND utc_date_time BETWEEN %s AND %s "
|
||||
" ORDER BY utc_date_time ")
|
||||
cursor_historical.execute(query, (point['id'],
|
||||
reporting_start_datetime_utc,
|
||||
reporting_end_datetime_utc))
|
||||
rows = cursor_historical.fetchall()
|
||||
|
||||
if rows is not None and len(rows) > 0:
|
||||
for row in rows:
|
||||
current_datetime_local = row[0].replace(tzinfo=timezone.utc) + \
|
||||
timedelta(minutes=timezone_offset)
|
||||
current_datetime = current_datetime_local.strftime('%Y-%m-%dT%H:%M:%S')
|
||||
point_timestamps.append(current_datetime)
|
||||
point_values.append(row[1])
|
||||
elif point['object_type'] == 'DIGITAL_VALUE':
|
||||
query = (" SELECT utc_date_time, actual_value "
|
||||
" FROM tbl_digital_value "
|
||||
" WHERE point_id = %s "
|
||||
" AND utc_date_time BETWEEN %s AND %s "
|
||||
" ORDER BY utc_date_time ")
|
||||
cursor_historical.execute(query, (point['id'],
|
||||
reporting_start_datetime_utc,
|
||||
reporting_end_datetime_utc))
|
||||
rows = cursor_historical.fetchall()
|
||||
|
||||
if rows is not None and len(rows) > 0:
|
||||
for row in rows:
|
||||
current_datetime_local = row[0].replace(tzinfo=timezone.utc) + \
|
||||
timedelta(minutes=timezone_offset)
|
||||
current_datetime = current_datetime_local.strftime('%Y-%m-%dT%H:%M:%S')
|
||||
point_timestamps.append(current_datetime)
|
||||
point_values.append(row[1])
|
||||
|
||||
parameters_data['names'].append(point['name'] + ' (' + point['units'] + ')')
|
||||
parameters_data['timestamps'].append(point_timestamps)
|
||||
parameters_data['values'].append(point_values)
|
||||
|
||||
################################################################################################################
|
||||
# Step 10: construct the report
|
||||
################################################################################################################
|
||||
if cursor_system:
|
||||
cursor_system.close()
|
||||
if cnx_system:
|
||||
cnx_system.disconnect()
|
||||
|
||||
if cursor_carbon:
|
||||
cursor_carbon.close()
|
||||
if cnx_carbon:
|
||||
cnx_carbon.disconnect()
|
||||
|
||||
if cursor_billing:
|
||||
cursor_billing.close()
|
||||
if cnx_billing:
|
||||
cnx_billing.disconnect()
|
||||
|
||||
if cursor_historical:
|
||||
cursor_historical.close()
|
||||
if cnx_historical:
|
||||
cnx_historical.disconnect()
|
||||
result = {
|
||||
"meter": {
|
||||
"cost_center_id": meter['cost_center_id'],
|
||||
"energy_category_id": meter['energy_category_id'],
|
||||
"energy_category_name": meter['energy_category_name'],
|
||||
"unit_of_measure": config.currency_unit,
|
||||
"kgce": meter['kgce'],
|
||||
"kgco2e": meter['kgco2e'],
|
||||
},
|
||||
"base_period": {
|
||||
"total_in_category": base['total_in_category'],
|
||||
"total_in_kgce": base['total_in_kgce'],
|
||||
"total_in_kgco2e": base['total_in_kgco2e'],
|
||||
"timestamps": base['timestamps'],
|
||||
"values": base['values'],
|
||||
},
|
||||
"reporting_period": {
|
||||
"increment_rate":
|
||||
(reporting['total_in_category']-base['total_in_category'])/base['total_in_category']
|
||||
if base['total_in_category'] > 0 else None,
|
||||
"total_in_category": reporting['total_in_category'],
|
||||
"total_in_kgce": reporting['total_in_kgce'],
|
||||
"total_in_kgco2e": reporting['total_in_kgco2e'],
|
||||
"timestamps": reporting['timestamps'],
|
||||
"values": reporting['values'],
|
||||
},
|
||||
"parameters": {
|
||||
"names": parameters_data['names'],
|
||||
"timestamps": parameters_data['timestamps'],
|
||||
"values": parameters_data['values']
|
||||
},
|
||||
}
|
||||
# export result to Excel file and then encode the file to base64 string
|
||||
result['excel_bytes_base64'] = \
|
||||
excelexporters.metercost.export(result,
|
||||
meter['name'],
|
||||
reporting_period_start_datetime_local,
|
||||
reporting_period_end_datetime_local,
|
||||
period_type)
|
||||
|
||||
resp.text = json.dumps(result)
|
Loading…
Reference in New Issue