Passed
Push — master ( 47dbe5...2b872a )
by
unknown
11:02 queued 14s
created

reports.energystoragepowerstationlist   C

Complexity

Total Complexity 54

Size/Duplication

Total Lines 356
Duplicated Lines 13.48 %

Importance

Changes 0
Metric Value
wmc 54
eloc 215
dl 48
loc 356
rs 6.4799
c 0
b 0
f 0

3 Methods

Rating   Name   Duplication   Size   Complexity  
A Reporting.on_options() 0 3 1
A Reporting.__init__() 0 3 1
F Reporting.on_get() 48 337 52

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complexity

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like reports.energystoragepowerstationlist often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

1
import falcon
2
from datetime import datetime, timedelta, timezone
3
import mysql.connector
4
import simplejson as json
5
from decimal import Decimal
6
from core.useractivity import access_control
7
import config
8
9
10
class Reporting:
11
    def __init__(self):
12
        """Initializes Class"""
13
        pass
14
15
    @staticmethod
16
    def on_options(req, resp):
17
        resp.status = falcon.HTTP_200
18
19
    @staticmethod
20
    def on_get(req, resp):
21
        access_control(req)
22
        # Get user inforamtion
23
        user_uuid = str.strip(req.headers['USER-UUID'])
24
        cnx_user_db = mysql.connector.connect(**config.myems_user_db)
25
        cursor_user_db = cnx_user_db.cursor()
26
        query = (" SELECT id "
27
                 " FROM tbl_users "
28
                 " WHERE uuid = %s ")
29
        cursor_user_db.execute(query, (user_uuid,))
30
        row = cursor_user_db.fetchone()
31
        cursor_user_db.close()
32
        cnx_user_db.close()
33
        if row is None:
34
            raise falcon.HTTPError(status=falcon.HTTP_400,
35
                                   title='API.BAD_REQUEST',
36
                                   description='API.INVALID_PRIVILEGE')
37
        user_id = row[0]
38
39
        # Get all points latest values
40
        digital_value_latest_dict = dict()
41
        analog_value_latest_dict = dict()
42
43
        cnx_historical_db = mysql.connector.connect(**config.myems_historical_db)
44
        cursor_historical_db = cnx_historical_db.cursor()
45
        query = (" SELECT point_id, utc_date_time, actual_value "
46
                 " FROM tbl_digital_value_latest ")
47
        cursor_historical_db.execute(query, )
48
        rows = cursor_historical_db.fetchall()
49
        if rows is not None and len(rows) > 0:
50
            for row in rows:
51
                digital_value_latest_dict[row[0]] = {"utc_date_time": row[1],
52
                                                     "actual_value": row[2]}
53
        query = (" SELECT point_id, utc_date_time, actual_value "
54
                 " FROM tbl_analog_value_latest ")
55
        cursor_historical_db.execute(query,)
56
        rows = cursor_historical_db.fetchall()
57
        cursor_historical_db.close()
58
        cnx_historical_db.close()
59
        if rows is not None and len(rows) > 0:
60
            for row in rows:
61
                analog_value_latest_dict[row[0]] = {"utc_date_time": row[1],
62
                                                    "actual_value": row[2]}
63
64
        # get charge data in latest 24 hours
65
        timezone_offset = int(config.utc_offset[1:3]) * 60 + int(config.utc_offset[4:6])
66
        if config.utc_offset[0] == '-':
67
            timezone_offset = -timezone_offset
68
        reporting_end_datetime_utc = datetime.utcnow().replace(minute=0, second=0, microsecond=0)
69
        reporting_start_datetime_utc = reporting_end_datetime_utc - timedelta(hours=24)
70
        today_start_datetime_local = (reporting_end_datetime_utc.replace(tzinfo=timezone.utc) +
71
                                      timedelta(minutes=timezone_offset)).replace(hour=0, minute=0, second=0,
72
                                                                                  microsecond=0)
73
        charge_report_dict = dict()
74
        cnx_energy_db = mysql.connector.connect(**config.myems_energy_db)
75
        cursor_energy_db = cnx_energy_db.cursor()
76
77
        cursor_energy_db.execute(" SELECT energy_storage_power_station_id, start_datetime_utc, actual_value "
78
                                 " FROM tbl_energy_storage_power_station_charge_hourly "
79
                                 " WHERE start_datetime_utc >= %s "
80
                                 "     AND start_datetime_utc < %s "
81
                                 " ORDER BY energy_storage_power_station_id, start_datetime_utc ",
82
                                 (reporting_start_datetime_utc,
83
                                  reporting_end_datetime_utc))
84
        rows_hourly = cursor_energy_db.fetchall()
85 View Code Duplication
        if rows_hourly is not None and len(rows_hourly) > 0:
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
86
            for row_hourly in rows_hourly:
87
                if row_hourly[0] not in charge_report_dict.keys():
88
                    charge_report_dict[row_hourly[0]] = dict()
89
                    charge_report_dict[row_hourly[0]]['charge_times'] = list()
90
                    charge_report_dict[row_hourly[0]]['charge_values'] = list()
91
                    # today total charge, not 24 hours
92
                    charge_report_dict[row_hourly[0]]['today_total_charge'] = Decimal(0.0)
93
94
                current_datetime_local = row_hourly[1].replace(tzinfo=timezone.utc) + timedelta(
95
                    minutes=timezone_offset)
96
                charge_report_dict[row_hourly[0]]['charge_times'].append(
97
                    current_datetime_local.isoformat()[11:16])
98
                actual_value = Decimal(0.0) if row_hourly[2] is None else row_hourly[2]
99
                charge_report_dict[row_hourly[0]]['charge_values'].append(actual_value)
100
                if current_datetime_local >= current_datetime_local:
101
                    charge_report_dict[row_hourly[0]]['today_total_charge'] += actual_value
102
103
        # get discharge data in latest 24 hours
104
        discharge_report_dict = dict()
105
        cursor_energy_db.execute(" SELECT energy_storage_power_station_id, start_datetime_utc, actual_value "
106
                                 " FROM tbl_energy_storage_power_station_discharge_hourly "
107
                                 " WHERE start_datetime_utc >= %s "
108
                                 "     AND start_datetime_utc < %s "
109
                                 " ORDER BY energy_storage_power_station_id, start_datetime_utc ",
110
                                 (reporting_start_datetime_utc,
111
                                  reporting_end_datetime_utc))
112
        rows_hourly = cursor_energy_db.fetchall()
113 View Code Duplication
        if rows_hourly is not None and len(rows_hourly) > 0:
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
114
            for row_hourly in rows_hourly:
115
                if row_hourly[0] not in discharge_report_dict.keys():
116
                    discharge_report_dict[row_hourly[0]] = dict()
117
                    discharge_report_dict[row_hourly[0]]['discharge_times'] = list()
118
                    discharge_report_dict[row_hourly[0]]['discharge_values'] = list()
119
                    # today total discharge, not 24 hours
120
                    discharge_report_dict[row_hourly[0]]['today_total_discharge'] = Decimal(0.0)
121
122
                current_datetime_local = row_hourly[1].replace(tzinfo=timezone.utc) + timedelta(
123
                    minutes=timezone_offset)
124
                discharge_report_dict[row_hourly[0]]['discharge_times'].append(
125
                    current_datetime_local.isoformat()[11:16])
126
                actual_value = Decimal(0.0) if row_hourly[2] is None else row_hourly[2]
127
                discharge_report_dict[row_hourly[0]]['discharge_values'].append(actual_value)
128
                if current_datetime_local >= current_datetime_local:
129
                    discharge_report_dict[row_hourly[0]]['today_total_discharge'] += actual_value
130
131
        cursor_energy_db.close()
132
        cnx_energy_db.close()
133
134
        default_time_list = list()
135
        default_value_list = list()
136
137
        start_datetime_local = reporting_start_datetime_utc.replace(tzinfo=timezone.utc) + timedelta(
138
            minutes=timezone_offset)
139
        end_datetime_local = reporting_end_datetime_utc.replace(tzinfo=timezone.utc) + timedelta(
140
            minutes=timezone_offset)
141
        current_datetime_local = start_datetime_local
142
        while current_datetime_local < end_datetime_local:
143
            default_time_list.append(current_datetime_local.isoformat()[11:16])
144
            default_value_list.append(Decimal(0.0))
145
            current_datetime_local = current_datetime_local + timedelta(hours=1)
146
147
        # get energy storage power stations
148
        cnx_system_db = mysql.connector.connect(**config.myems_system_db)
149
        cursor_system_db = cnx_system_db.cursor()
150
        query = (" SELECT m.id, m.name, m.uuid, "
151
                 "        m.address, m.latitude, m.longitude, m.rated_capacity, m.rated_power, "
152
                 "        m.description, m.phase_of_lifecycle, m.commissioning_date "
153
                 " FROM tbl_energy_storage_power_stations m, tbl_energy_storage_power_stations_users mu "
154
                 " WHERE m.id = mu.energy_storage_power_station_id AND mu.user_id = %s "
155
                 " ORDER BY m.phase_of_lifecycle, m.id ")
156
        cursor_system_db.execute(query, (user_id, ))
157
        rows_energy_storage_power_stations = cursor_system_db.fetchall()
158
159
        # construct the report
160
        result = list()
161
        if rows_energy_storage_power_stations is not None and len(rows_energy_storage_power_stations) > 0:
162
            for row in rows_energy_storage_power_stations:
163
                energy_storage_power_station_id = row[0]
164
                # get is_online by data source latest seen datetime
165
                query = (" SELECT tds.last_seen_datetime_utc   "
166
                         " FROM tbl_energy_storage_power_stations_containers tespsesc, "
167
                         "      tbl_energy_storage_containers_power_conversion_systems tescpcs, "
168
                         "      tbl_points tp, tbl_data_sources tds  "
169
                         " WHERE tespsesc.energy_storage_power_station_id  = %s "
170
                         "        AND tespsesc.energy_storage_container_id = tescpcs.energy_storage_container_id  "
171
                         "        AND tescpcs.run_state_point_id = tp.id  "
172
                         "        AND tp.data_source_id = tds.id  "
173
                         " LIMIT 1 ")
174
                cursor_system_db.execute(query, (energy_storage_power_station_id,))
175
                row_datetime = cursor_system_db.fetchone()
176
177
                is_online = False
178
                if row_datetime is not None and len(row_datetime) > 0:
179
                    if isinstance(row_datetime[0], datetime):
180
                        if row_datetime[0] + timedelta(minutes=10) > datetime.utcnow():
181
                            is_online = True
182
183
                # get PCS run state point
184
                pcs_run_state_point_value = None
185
                if is_online:
186
                    query = (" SELECT tescpcs.run_state_point_id "
187
                             " FROM tbl_energy_storage_power_stations_containers tespsesc, "
188
                             "     tbl_energy_storage_containers_power_conversion_systems tescpcs "
189
                             " WHERE tespsesc.energy_storage_power_station_id  = %s "
190
                             "       AND tespsesc.energy_storage_container_id = tescpcs.energy_storage_container_id "
191
                             " LIMIT 1 ")
192
                    cursor_system_db.execute(query, (energy_storage_power_station_id,))
193
                    row_point = cursor_system_db.fetchone()
194
                    if row_point is not None and len(row_point) > 0:
195
                        if digital_value_latest_dict.get(row_point[0]) is not None:
196
                            pcs_run_state_point_value = digital_value_latest_dict.get(row_point[0])['actual_value']
197
198
                # 鸿博:关联PCS开机关机指令设置,.0为停机,1为运行
199
                if pcs_run_state_point_value is None:
200
                    pcs_run_state = 'Unknown'
201
                elif pcs_run_state_point_value == 0:
202
                    pcs_run_state = 'Shutdown'
203
                elif pcs_run_state_point_value == 1:
204
                    pcs_run_state = 'Running'
205
                else:
206
                    pcs_run_state = 'Unknown'
207
208
                # MyEMS标准状态
209
                # 0:关闭 Shutdown
210
                # 1:软启动中 Soft Starting
211
                # 2:并网充电 On Grid Charging
212
                # 3:并网放电 On Grid DisCharging
213
                # 4:离网放电 Off Grid DisCharging
214
                # 5:降额并网 Derating On Grid
215
                # 6:待机 Standby
216
                # 7:离网充电 Off Grid Charging
217
                #
218
                # if pcs_run_state_point_value is None:
219
                #     pcs_run_state = 'Unknown'
220
                # elif pcs_run_state_point_value == 0:
221
                #     pcs_run_state = 'Shutdown'
222
                # elif pcs_run_state_point_value == 1:
223
                #     pcs_run_state = 'Running'
224
                # elif pcs_run_state_point_value == 2:
225
                #     pcs_run_state = 'Running'
226
                # elif pcs_run_state_point_value == 3:
227
                #     pcs_run_state = 'Running'
228
                # elif pcs_run_state_point_value == 4:
229
                #     pcs_run_state = 'Running'
230
                # elif pcs_run_state_point_value == 5:
231
                #     pcs_run_state = 'Running'
232
                # elif pcs_run_state_point_value == 6:
233
                #     pcs_run_state = 'Standby'
234
                # elif pcs_run_state_point_value == 7:
235
                #     pcs_run_state = 'Running'
236
                # else:
237
                #     pcs_run_state = 'Running'
238
239
                # get battery state point
240
                battery_state_point_value = None
241
                if is_online:
242
                    query = (" SELECT tescb.battery_state_point_id "
243
                             " FROM tbl_energy_storage_power_stations_containers tespsesc, "
244
                             "      tbl_energy_storage_containers_batteries tescb "
245
                             " WHERE tespsesc.energy_storage_power_station_id = %s "
246
                             "       AND tespsesc.energy_storage_container_id = tescb.energy_storage_container_id "
247
                             " LIMIT 1 ")
248
                    cursor_system_db.execute(query, (energy_storage_power_station_id,))
249
                    row_point = cursor_system_db.fetchone()
250
                    if row_point is not None and len(row_point) > 0:
251
                        if digital_value_latest_dict.get(row_point[0]) is not None:
252
                            battery_state_point_value = digital_value_latest_dict.get(row_point[0])['actual_value']
253
254
                # MyEMS 0预留 1故障  2预警  3待机  4禁放  5禁充  6正常 7充电 8放电 9空闲
255
                # 鸿博 1 充电 2放电 3开路
256
                print(battery_state_point_value)
257
                if battery_state_point_value is None:
258
                    battery_operating_state = 'Unknown'
259
                elif battery_state_point_value == 1:
260
                    battery_operating_state = 'Charging'
261
                elif battery_state_point_value == 2:
262
                    battery_operating_state = 'Discharging'
263
                elif battery_state_point_value == 3:
264
                    battery_operating_state = 'Idle'
265
                else:
266
                    battery_operating_state = 'Unknown'
267
                # if battery_state_point_value is None:
268
                #     battery_operating_state = 'Unknown'
269
                # elif battery_state_point_value == 0:
270
                #     battery_operating_state = 'Reserved'
271
                # elif battery_state_point_value == 1:
272
                #     battery_operating_state = 'Fault'
273
                # elif battery_state_point_value == 2:
274
                #     battery_operating_state = 'Warning'
275
                # elif battery_state_point_value == 3:
276
                #     battery_operating_state = 'Standby'
277
                # elif battery_state_point_value == 4:
278
                #     battery_operating_state = 'ProhibitDisCharging'
279
                # elif battery_state_point_value == 5:
280
                #     battery_operating_state = 'ProhibitCharging'
281
                # elif battery_state_point_value == 6:
282
                #     battery_operating_state = 'Normal'
283
                # elif battery_state_point_value == 7:
284
                #     battery_operating_state = 'Charging'
285
                # elif battery_state_point_value == 8:
286
                #     battery_operating_state = 'Discharging'
287
                # elif battery_state_point_value == 9:
288
                #     battery_operating_state = 'Idle'
289
                # else:
290
                #     battery_operating_state = 'Unknown'
291
292
                # get battery soc point, power point
293
                battery_soc_point_value = None
294
                battery_power_point_value = None
295 View Code Duplication
                if is_online:
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
296
                    query = (" SELECT tescb.soc_point_id, tescb.power_point_id "
297
                             " FROM tbl_energy_storage_power_stations_containers tespsc, "
298
                             "      tbl_energy_storage_containers_batteries tescb "
299
                             " WHERE tespsc.energy_storage_power_station_id = %s "
300
                             "       AND tespsc.energy_storage_container_id = tescb.energy_storage_container_id "
301
                             " LIMIT 1 ")
302
                    cursor_system_db.execute(query, (energy_storage_power_station_id,))
303
                    row_point = cursor_system_db.fetchone()
304
                    if row_point is not None and len(row_point) > 0:
305
                        if analog_value_latest_dict.get(row_point[0]) is not None:
306
                            battery_soc_point_value = analog_value_latest_dict.get(row_point[0])['actual_value']
307
                        if analog_value_latest_dict.get(row_point[1]) is not None:
308
                            battery_power_point_value = analog_value_latest_dict.get(row_point[1])['actual_value']
309
310
                # complete the charge_report_dict
311
                if energy_storage_power_station_id not in charge_report_dict.keys():
312
                    charge_report_dict[energy_storage_power_station_id] = dict()
313
                    charge_report_dict[energy_storage_power_station_id]['charge_times'] = default_time_list
314
                    charge_report_dict[energy_storage_power_station_id]['charge_values'] = default_value_list
315
                    charge_report_dict[energy_storage_power_station_id]['today_total_charge'] = Decimal(0.0)
316
317
                if energy_storage_power_station_id not in discharge_report_dict.keys():
318
                    discharge_report_dict[energy_storage_power_station_id] = dict()
319
                    discharge_report_dict[energy_storage_power_station_id]['discharge_times'] = default_time_list
320
                    discharge_report_dict[energy_storage_power_station_id]['discharge_values'] = default_value_list
321
                    discharge_report_dict[energy_storage_power_station_id]['today_total_discharge'] = Decimal(0.0)
322
323
                meta_result = {"id": energy_storage_power_station_id,
324
                               "name": row[1],
325
                               "uuid": row[2],
326
                               "address": row[3],
327
                               "latitude": row[4],
328
                               "longitude": row[5],
329
                               "rated_capacity": row[6],
330
                               "rated_power": row[7],
331
                               "description": row[8],
332
                               "phase_of_lifecycle": row[9],
333
                               "commissioning_date": str(row[10]) if row[10] is not None else None,
334
                               "qrcode": 'energystoragepowerstation:' + row[2],
335
                               "is_online": is_online,
336
                               "pcs_run_state": pcs_run_state,
337
                               "battery_operating_state": battery_operating_state,
338
                               "battery_soc_point_value": battery_soc_point_value,
339
                               "battery_power_point_value": battery_power_point_value,
340
                               "charge_times": charge_report_dict[energy_storage_power_station_id]['charge_times'],
341
                               "charge_values": charge_report_dict[energy_storage_power_station_id]['charge_values'],
342
                               "today_total_charge":
343
                                   charge_report_dict[energy_storage_power_station_id]['today_total_charge'],
344
                               "discharge_times":
345
                                   discharge_report_dict[energy_storage_power_station_id]['discharge_times'],
346
                               "discharge_values":
347
                                   discharge_report_dict[energy_storage_power_station_id]['discharge_values'],
348
                               "today_total_discharge":
349
                                   discharge_report_dict[energy_storage_power_station_id]['today_total_discharge'],
350
                               }
351
                result.append(meta_result)
352
353
        cursor_system_db.close()
354
        cnx_system_db.close()
355
        resp.text = json.dumps(result)
356