1
|
|
|
import falcon |
2
|
|
|
import simplejson as json |
3
|
|
|
import mysql.connector |
4
|
|
|
import config |
5
|
|
|
from datetime import datetime, timedelta, timezone |
6
|
|
|
|
7
|
|
|
|
8
|
|
|
class Reporting: |
9
|
|
|
@staticmethod |
10
|
|
|
def __init__(): |
11
|
|
|
pass |
12
|
|
|
|
13
|
|
|
@staticmethod |
14
|
|
|
def on_options(req, resp): |
15
|
|
|
resp.status = falcon.HTTP_200 |
16
|
|
|
|
17
|
|
|
#################################################################################################################### |
18
|
|
|
# PROCEDURES |
19
|
|
|
# Step 1: valid parameters |
20
|
|
|
# Step 2: query the distribution system |
21
|
|
|
# Step 3: query associated circuits |
22
|
|
|
# Step 4: query circuits' associated points |
23
|
|
|
# Step 5: query points' latest values |
24
|
|
|
# Step 6: construct the report |
25
|
|
|
#################################################################################################################### |
26
|
|
|
@staticmethod |
27
|
|
|
def on_get(req, resp): |
28
|
|
|
print(req.params) |
29
|
|
|
distribution_system_id = req.params.get('distributionsystemid') |
30
|
|
|
|
31
|
|
|
################################################################################################################ |
32
|
|
|
# Step 1: valid parameters |
33
|
|
|
################################################################################################################ |
34
|
|
|
if distribution_system_id is None: |
35
|
|
|
raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST', |
36
|
|
|
description='API.INVALID_DISTRIBUTION_SYSTEM_ID') |
37
|
|
|
else: |
38
|
|
|
distribution_system_id = str.strip(distribution_system_id) |
39
|
|
|
if not distribution_system_id.isdigit() or int(distribution_system_id) <= 0: |
40
|
|
|
raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST', |
41
|
|
|
description='API.INVALID_DISTRIBUTION_SYSTEM_ID') |
42
|
|
|
# set the earliest datetime of valid actual value |
43
|
|
|
# if the utc_date_time is less than reporting_start_datetime_utc, then the value is None because of timeout |
44
|
|
|
reporting_start_datetime_utc = datetime.utcnow() - timedelta(minutes=5) |
45
|
|
|
|
46
|
|
|
################################################################################################################ |
47
|
|
|
# Step 2: Step 2: query the distribution system |
48
|
|
|
################################################################################################################ |
49
|
|
|
cnx_system = mysql.connector.connect(**config.myems_system_db) |
50
|
|
|
cursor_system = cnx_system.cursor(dictionary=True) |
51
|
|
|
|
52
|
|
|
cursor_system.execute(" SELECT name " |
53
|
|
|
" FROM tbl_distribution_systems " |
54
|
|
|
" WHERE id = %s ", (distribution_system_id,)) |
55
|
|
|
if cursor_system.fetchone() is None: |
56
|
|
|
if cursor_system: |
57
|
|
|
cursor_system.close() |
58
|
|
|
if cnx_system: |
59
|
|
|
cnx_system.disconnect() |
60
|
|
|
raise falcon.HTTPError(falcon.HTTP_404, title='API.NOT_FOUND', |
61
|
|
|
description='API.DISTRIBUTION_SYSTEM_NOT_FOUND') |
62
|
|
|
|
63
|
|
|
################################################################################################################ |
64
|
|
|
# Step 3: query associated circuits |
65
|
|
|
################################################################################################################ |
66
|
|
|
query = (" SELECT id, name, uuid, " |
67
|
|
|
" distribution_room, switchgear, peak_load, peak_current, customers, meters " |
68
|
|
|
" FROM tbl_distribution_circuits " |
69
|
|
|
" WHERE distribution_system_id = %s " |
70
|
|
|
" ORDER BY name ") |
71
|
|
|
cursor_system.execute(query, (distribution_system_id,)) |
72
|
|
|
rows = cursor_system.fetchall() |
73
|
|
|
|
74
|
|
|
circuit_list = list() |
75
|
|
|
if rows is not None and len(rows) > 0: |
76
|
|
|
for row in rows: |
77
|
|
|
circuit_list.append({"id": row['id'], "name": row['name'], "uuid": row['uuid'], |
78
|
|
|
"distribution_room": row['distribution_room'], "switchgear": row['switchgear'], |
79
|
|
|
"peak_load": row['peak_load'], "peak_current": row['peak_current'], |
80
|
|
|
"customers": row['customers'], "meters": row['meters'], |
81
|
|
|
"points": list()}) |
82
|
|
|
|
83
|
|
|
################################################################################################################ |
84
|
|
|
# Step 4: query circuits' associated points |
85
|
|
|
################################################################################################################ |
86
|
|
|
for x in range(len(circuit_list)): |
87
|
|
|
query = (" SELECT p.id, p.name, p.object_type, p.units " |
88
|
|
|
" FROM tbl_points p, tbl_distribution_circuits_points dcp, tbl_distribution_circuits dc " |
89
|
|
|
" WHERE dcp.distribution_circuit_id = %s AND p.id = dcp.point_id " |
90
|
|
|
" AND dcp.distribution_circuit_id = dc.id " |
91
|
|
|
" ORDER BY p.name ") |
92
|
|
|
cursor_system.execute(query, (circuit_list[x]['id'],)) |
93
|
|
|
rows = cursor_system.fetchall() |
94
|
|
|
|
95
|
|
|
if rows is not None and len(rows) > 0: |
96
|
|
|
for row in rows: |
97
|
|
|
circuit_list[x]['points'].append({"id": row['id'], |
98
|
|
|
"name": row['name'], |
99
|
|
|
"object_type": row['object_type'], |
100
|
|
|
"units": row['units'], |
101
|
|
|
"value": None}) |
102
|
|
|
if cursor_system: |
103
|
|
|
cursor_system.close() |
104
|
|
|
if cnx_system: |
105
|
|
|
cnx_system.disconnect() |
106
|
|
|
################################################################################################################ |
107
|
|
|
# Step 5: query points' data |
108
|
|
|
################################################################################################################ |
109
|
|
|
cnx_historical = mysql.connector.connect(**config.myems_historical_db) |
110
|
|
|
cursor_historical = cnx_historical.cursor() |
111
|
|
|
|
112
|
|
|
for x in range(len(circuit_list)): |
113
|
|
|
for y in range(len(circuit_list[x]['points'])): |
114
|
|
|
if circuit_list[x]['points'][y]['object_type'] == 'ANALOG_VALUE': |
115
|
|
|
|
116
|
|
|
query = (" SELECT actual_value " |
117
|
|
|
" FROM tbl_analog_value_latest " |
118
|
|
|
" WHERE point_id = %s " |
119
|
|
|
" AND utc_date_time > %s ") |
120
|
|
|
cursor_historical.execute(query, (circuit_list[x]['points'][y]['id'], |
121
|
|
|
reporting_start_datetime_utc)) |
122
|
|
|
row = cursor_historical.fetchone() |
123
|
|
|
|
124
|
|
|
if row is not None: |
125
|
|
|
circuit_list[x]['points'][y]['value'] = row[0] |
126
|
|
|
|
127
|
|
|
elif circuit_list[x]['points'][y]['object_type'] == 'ENERGY_VALUE': |
128
|
|
|
query = (" SELECT actual_value " |
129
|
|
|
" FROM tbl_energy_value_latest " |
130
|
|
|
" WHERE point_id = %s " |
131
|
|
|
" AND utc_date_time > %s ") |
132
|
|
|
cursor_historical.execute(query, (circuit_list[x]['points'][y]['id'], |
133
|
|
|
reporting_start_datetime_utc)) |
134
|
|
|
row = cursor_historical.fetchone() |
135
|
|
|
|
136
|
|
|
if row is not None: |
137
|
|
|
circuit_list[x]['points'][y]['value'] = row[0] |
138
|
|
|
|
139
|
|
|
elif circuit_list[x]['points'][y]['object_type'] == 'DIGITAL_VALUE': |
140
|
|
|
query = (" SELECT actual_value " |
141
|
|
|
" FROM tbl_digital_value_latest " |
142
|
|
|
" WHERE point_id = %s " |
143
|
|
|
" AND utc_date_time > %s ") |
144
|
|
|
cursor_historical.execute(query, (circuit_list[x]['points'][y]['id'], |
145
|
|
|
reporting_start_datetime_utc)) |
146
|
|
|
row = cursor_historical.fetchone() |
147
|
|
|
|
148
|
|
|
if row is not None: |
149
|
|
|
circuit_list[x]['points'][y]['value'] = row[0] |
150
|
|
|
|
151
|
|
|
if cursor_historical: |
152
|
|
|
cursor_historical.close() |
153
|
|
|
if cnx_historical: |
154
|
|
|
cnx_historical.disconnect() |
155
|
|
|
|
156
|
|
|
################################################################################################################ |
157
|
|
|
# Step 6: construct the report |
158
|
|
|
################################################################################################################ |
159
|
|
|
|
160
|
|
|
result = circuit_list |
161
|
|
|
|
162
|
|
|
resp.body = json.dumps(result) |
163
|
|
|
|