core.energyflowdiagram   F
last analyzed

Complexity

Total Complexity 346

Size/Duplication

Total Lines 1762
Duplicated Lines 12.94 %

Importance

Changes 0
Metric Value
wmc 346
eloc 1331
dl 228
loc 1762
rs 0.8
c 0
b 0
f 0

36 Methods

Rating   Name   Duplication   Size   Complexity  
F EnergyFlowDiagramCollection.on_get() 0 110 26
A EnergyFlowDiagramCollection.__init__() 0 3 1
B EnergyFlowDiagramCollection.on_post() 0 46 6
A EnergyFlowDiagramItem.__init__() 0 3 1
A EnergyFlowDiagramItem.on_options() 0 5 1
A EnergyFlowDiagramCollection.on_options() 0 4 1
F EnergyFlowDiagramItem.on_get() 114 114 26
C EnergyFlowDiagramItem.on_put() 0 57 9
B EnergyFlowDiagramItem.on_delete() 0 41 5
A EnergyFlowDiagramLinkCollection.__init__() 0 3 1
A EnergyFlowDiagramNodeCollection.__init__() 0 3 1
A EnergyFlowDiagramLinkItem.__init__() 0 3 1
B EnergyFlowDiagramLinkItem.on_delete() 0 47 7
A EnergyFlowDiagramLinkCollection.on_options() 0 5 1
A EnergyFlowDiagramNodeCollection.on_options() 0 5 1
C EnergyFlowDiagramNodeCollection.on_post() 0 58 9
A EnergyFlowDiagramLinkItem.on_options() 0 5 1
F EnergyFlowDiagramLinkCollection.on_get() 0 102 24
A EnergyFlowDiagramNodeItem.on_options() 0 5 1
B EnergyFlowDiagramNodeItem.on_get() 0 30 6
A EnergyFlowDiagramNodeItem.__init__() 0 3 1
F EnergyFlowDiagramLinkItem.on_get() 0 90 20
F EnergyFlowDiagramLinkItem.on_put() 0 162 33
C EnergyFlowDiagramNodeCollection.on_get() 0 41 10
F EnergyFlowDiagramLinkCollection.on_post() 0 146 30
A EnergyFlowDiagramExport.__init__() 0 3 1
D EnergyFlowDiagramNodeItem.on_put() 0 75 12
A EnergyFlowDiagramImport.__init__() 0 3 1
A EnergyFlowDiagramImport.on_options() 0 4 1
A EnergyFlowDiagramClone.on_options() 0 5 1
F EnergyFlowDiagramExport.on_get() 114 114 26
A EnergyFlowDiagramExport.on_options() 0 5 1
F EnergyFlowDiagramImport.on_post() 0 196 39
C EnergyFlowDiagramNodeItem.on_delete() 0 60 9
A EnergyFlowDiagramClone.__init__() 0 3 1
F EnergyFlowDiagramClone.on_post() 0 141 31

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 core.energyflowdiagram 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 uuid
2
from datetime import datetime, timedelta
3
import falcon
4
import mysql.connector
5
import simplejson as json
6
from core.useractivity import user_logger, admin_control, access_control, api_key_control
7
import config
8
9
10
class EnergyFlowDiagramCollection:
11
    def __init__(self):
12
        """"Initializes EnergyFlowDiagramCollection"""
13
        pass
14
15
    @staticmethod
16
    def on_options(req, resp):
17
        _ = req
18
        resp.status = falcon.HTTP_200
19
20
    @staticmethod
21
    def on_get(req, resp):
22
        if 'API-KEY' not in req.headers or \
23
                not isinstance(req.headers['API-KEY'], str) or \
24
                len(str.strip(req.headers['API-KEY'])) == 0:
25
            access_control(req)
26
        else:
27
            api_key_control(req)
28
        cnx = mysql.connector.connect(**config.myems_system_db)
29
        cursor = cnx.cursor()
30
31
        query = (" SELECT id, name, uuid "
32
                 " FROM tbl_meters ")
33
        cursor.execute(query)
34
        rows_meters = cursor.fetchall()
35
36
        meter_dict = dict()
37
        if rows_meters is not None and len(rows_meters) > 0:
38
            for row in rows_meters:
39
                meter_dict[row[2]] = {"type": 'meter',
40
                                      "id": row[0],
41
                                      "name": row[1],
42
                                      "uuid": row[2]}
43
44
        query = (" SELECT id, name, uuid "
45
                 " FROM tbl_offline_meters ")
46
        cursor.execute(query)
47
        rows_offline_meters = cursor.fetchall()
48
49
        offline_meter_dict = dict()
50
        if rows_offline_meters is not None and len(rows_offline_meters) > 0:
51
            for row in rows_offline_meters:
52
                offline_meter_dict[row[2]] = {"type": 'offline_meter',
53
                                              "id": row[0],
54
                                              "name": row[1],
55
                                              "uuid": row[2]}
56
57
        query = (" SELECT id, name, uuid "
58
                 " FROM tbl_virtual_meters ")
59
        cursor.execute(query)
60
        rows_virtual_meters = cursor.fetchall()
61
62
        virtual_meter_dict = dict()
63
        if rows_virtual_meters is not None and len(rows_virtual_meters) > 0:
64
            for row in rows_virtual_meters:
65
                virtual_meter_dict[row[2]] = {"type": 'virtual_meter',
66
                                              "id": row[0],
67
                                              "name": row[1],
68
                                              "uuid": row[2]}
69
70
        query = (" SELECT id, energy_flow_diagram_id, name "
71
                 " FROM tbl_energy_flow_diagrams_nodes")
72
        cursor.execute(query)
73
        rows_nodes = cursor.fetchall()
74
75
        node_dict = dict()
76
        node_list_dict = dict()
77
        if rows_nodes is not None and len(rows_nodes) > 0:
78
            for row in rows_nodes:
79
                node_dict[row[0]] = row[2]
80
                if node_list_dict.get(row[1]) is None:
81
                    node_list_dict[row[1]] = list()
82
                node_list_dict[row[1]].append({"id": row[0], "name": row[2]})
83
84
        query = (" SELECT id, energy_flow_diagram_id, source_node_id, target_node_id, meter_uuid "
85
                 " FROM tbl_energy_flow_diagrams_links")
86
        cursor.execute(query)
87
        rows_links = cursor.fetchall()
88
89
        link_list_dict = dict()
90
        if rows_links is not None and len(rows_links) > 0:
91
            for row in rows_links:
92
                # find meter by uuid
93
                meter = meter_dict.get(row[4], None)
94
                if meter is None:
95
                    meter = virtual_meter_dict.get(row[4], None)
96
                if meter is None:
97
                    meter = offline_meter_dict.get(row[4], None)
98
99
                if link_list_dict.get(row[1]) is None:
100
                    link_list_dict[row[1]] = list()
101
                link_list_dict[row[1]].append({"id": row[0],
102
                                               "source_node": {
103
                                                   "id": row[2],
104
                                                   "name": node_dict.get(row[2])},
105
                                               "target_node": {
106
                                                   "id": row[3],
107
                                                   "name": node_dict.get(row[3])},
108
                                               "meter": meter})
109
110
        query = (" SELECT id, name, uuid "
111
                 " FROM tbl_energy_flow_diagrams "
112
                 " ORDER BY id ")
113
        cursor.execute(query)
114
        rows_energy_flow_diagrams = cursor.fetchall()
115
116
        result = list()
117
        if rows_energy_flow_diagrams is not None and len(rows_energy_flow_diagrams) > 0:
118
            for row in rows_energy_flow_diagrams:
119
120
                meta_result = {"id": row[0],
121
                               "name": row[1],
122
                               "uuid": row[2],
123
                               "nodes": node_list_dict.get(row[0], None),
124
                               "links": link_list_dict.get(row[0], None), }
125
                result.append(meta_result)
126
127
        cursor.close()
128
        cnx.close()
129
        resp.text = json.dumps(result)
130
131
    @staticmethod
132
    @user_logger
133
    def on_post(req, resp):
134
        """Handles POST requests"""
135
        admin_control(req)
136
        try:
137
            raw_json = req.stream.read().decode('utf-8')
138
        except Exception as ex:
139
            print(str(ex))
140
            raise falcon.HTTPError(status=falcon.HTTP_400,
141
                                   title='API.BAD_REQUEST',
142
                                   description='API.FAILED_TO_READ_REQUEST_STREAM')
143
144
        new_values = json.loads(raw_json)
145
146
        if 'name' not in new_values['data'].keys() or \
147
                not isinstance(new_values['data']['name'], str) or \
148
                len(str.strip(new_values['data']['name'])) == 0:
149
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
150
                                   description='API.INVALID_ENERGY_FLOW_DIAGRAM_NAME')
151
        name = str.strip(new_values['data']['name'])
152
153
        cnx = mysql.connector.connect(**config.myems_system_db)
154
        cursor = cnx.cursor()
155
156
        cursor.execute(" SELECT name "
157
                       " FROM tbl_energy_flow_diagrams "
158
                       " WHERE name = %s ", (name,))
159
        if cursor.fetchone() is not None:
160
            cursor.close()
161
            cnx.close()
162
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
163
                                   description='API.ENERGY_FLOW_DIAGRAM_NAME_IS_ALREADY_IN_USE')
164
165
        add_values = (" INSERT INTO tbl_energy_flow_diagrams "
166
                      "    (name, uuid) "
167
                      " VALUES (%s, %s) ")
168
        cursor.execute(add_values, (name,
169
                                    str(uuid.uuid4())))
170
        new_id = cursor.lastrowid
171
        cnx.commit()
172
        cursor.close()
173
        cnx.close()
174
175
        resp.status = falcon.HTTP_201
176
        resp.location = '/energyflowdiagrams/' + str(new_id)
177
178
179
class EnergyFlowDiagramItem:
180
    def __init__(self):
181
        """"Initializes EnergyFlowDiagramItem"""
182
        pass
183
184
    @staticmethod
185
    def on_options(req, resp, id_):
186
        _ = req
187
        resp.status = falcon.HTTP_200
188
        _ = id_
189
190 View Code Duplication
    @staticmethod
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
191
    def on_get(req, resp, id_):
192
        if 'API-KEY' not in req.headers or \
193
                not isinstance(req.headers['API-KEY'], str) or \
194
                len(str.strip(req.headers['API-KEY'])) == 0:
195
            access_control(req)
196
        else:
197
            api_key_control(req)
198
        if not id_.isdigit() or int(id_) <= 0:
199
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
200
                                   description='API.INVALID_ENERGY_FLOW_DIAGRAM_ID')
201
202
        cnx = mysql.connector.connect(**config.myems_system_db)
203
        cursor = cnx.cursor()
204
205
        query = (" SELECT id, name, uuid "
206
                 " FROM tbl_meters ")
207
        cursor.execute(query)
208
        rows_meters = cursor.fetchall()
209
210
        meter_dict = dict()
211
        if rows_meters is not None and len(rows_meters) > 0:
212
            for row in rows_meters:
213
                meter_dict[row[2]] = {"type": 'meter',
214
                                      "id": row[0],
215
                                      "name": row[1],
216
                                      "uuid": row[2]}
217
218
        query = (" SELECT id, name, uuid "
219
                 " FROM tbl_offline_meters ")
220
        cursor.execute(query)
221
        rows_offline_meters = cursor.fetchall()
222
223
        offline_meter_dict = dict()
224
        if rows_offline_meters is not None and len(rows_offline_meters) > 0:
225
            for row in rows_offline_meters:
226
                offline_meter_dict[row[2]] = {"type": 'offline_meter',
227
                                              "id": row[0],
228
                                              "name": row[1],
229
                                              "uuid": row[2]}
230
231
        query = (" SELECT id, name, uuid "
232
                 " FROM tbl_virtual_meters ")
233
        cursor.execute(query)
234
        rows_virtual_meters = cursor.fetchall()
235
236
        virtual_meter_dict = dict()
237
        if rows_virtual_meters is not None and len(rows_virtual_meters) > 0:
238
            for row in rows_virtual_meters:
239
                virtual_meter_dict[row[2]] = {"type": 'virtual_meter',
240
                                              "id": row[0],
241
                                              "name": row[1],
242
                                              "uuid": row[2]}
243
244
        query = (" SELECT id, energy_flow_diagram_id, name "
245
                 " FROM tbl_energy_flow_diagrams_nodes")
246
        cursor.execute(query)
247
        rows_nodes = cursor.fetchall()
248
249
        node_dict = dict()
250
        node_list_dict = dict()
251
        if rows_nodes is not None and len(rows_nodes) > 0:
252
            for row in rows_nodes:
253
                node_dict[row[0]] = row[2]
254
                if node_list_dict.get(row[1]) is None:
255
                    node_list_dict[row[1]] = list()
256
                node_list_dict[row[1]].append({"id": row[0], "name": row[2]})
257
258
        query = (" SELECT id, energy_flow_diagram_id, source_node_id, target_node_id, meter_uuid "
259
                 " FROM tbl_energy_flow_diagrams_links")
260
        cursor.execute(query)
261
        rows_links = cursor.fetchall()
262
263
        link_list_dict = dict()
264
        if rows_links is not None and len(rows_links) > 0:
265
            for row in rows_links:
266
                # find meter by uuid
267
                meter = meter_dict.get(row[4], None)
268
                if meter is None:
269
                    meter = virtual_meter_dict.get(row[4], None)
270
                if meter is None:
271
                    meter = offline_meter_dict.get(row[4], None)
272
273
                if link_list_dict.get(row[1]) is None:
274
                    link_list_dict[row[1]] = list()
275
                link_list_dict[row[1]].append({"id": row[0],
276
                                               "source_node": {
277
                                                   "id": row[2],
278
                                                   "name": node_dict.get(row[2])},
279
                                               "target_node": {
280
                                                   "id": row[3],
281
                                                   "name": node_dict.get(row[3])},
282
                                               "meter": meter})
283
284
        query = (" SELECT id, name, uuid "
285
                 " FROM tbl_energy_flow_diagrams "
286
                 " WHERE id = %s ")
287
        cursor.execute(query, (id_,))
288
        row = cursor.fetchone()
289
        cursor.close()
290
        cnx.close()
291
292
        if row is None:
293
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
294
                                   description='API.ENERGY_FLOW_DIAGRAM_NOT_FOUND')
295
        else:
296
            meta_result = {"id": row[0],
297
                           "name": row[1],
298
                           "uuid": row[2],
299
                           "nodes": node_list_dict.get(row[0], None),
300
                           "links": link_list_dict.get(row[0], None),
301
                           }
302
303
        resp.text = json.dumps(meta_result)
304
305
    @staticmethod
306
    @user_logger
307
    def on_delete(req, resp, id_):
308
        admin_control(req)
309
        if not id_.isdigit() or int(id_) <= 0:
310
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
311
                                   description='API.INVALID_ENERGY_FLOW_DIAGRAM_ID')
312
313
        cnx = mysql.connector.connect(**config.myems_system_db)
314
        cursor = cnx.cursor()
315
316
        # check relation with spaces
317
        cursor.execute(" SELECT id "
318
                       " FROM  tbl_spaces_energy_flow_diagrams "
319
                       " WHERE energy_flow_diagram_id = %s ", (id_,))
320
        rows_spaces = cursor.fetchall()
321
        if rows_spaces is not None and len(rows_spaces) > 0:
322
            cursor.close()
323
            cnx.close()
324
            raise falcon.HTTPError(status=falcon.HTTP_400,
325
                                   title='API.BAD_REQUEST',
326
                                   description='API.THERE_IS_RELATION_WITH_SPACES')
327
328
        # delete all associated nodes
329
        cursor.execute(" DELETE FROM tbl_energy_flow_diagrams_nodes"
330
                       " WHERE energy_flow_diagram_id = %s ", (id_,))
331
        cnx.commit()
332
333
        # delete all associated links
334
        cursor.execute(" DELETE FROM tbl_energy_flow_diagrams_links"
335
                       " WHERE energy_flow_diagram_id = %s ", (id_,))
336
        cnx.commit()
337
338
        cursor.execute(" DELETE FROM tbl_energy_flow_diagrams"
339
                       " WHERE id = %s ", (id_,))
340
        cnx.commit()
341
342
        cursor.close()
343
        cnx.close()
344
345
        resp.status = falcon.HTTP_204
346
347
    @staticmethod
348
    @user_logger
349
    def on_put(req, resp, id_):
350
        """Handles PUT requests"""
351
        admin_control(req)
352
        if not id_.isdigit() or int(id_) <= 0:
353
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
354
                                   description='API.INVALID_ENERGY_FLOW_DIAGRAM_ID')
355
        try:
356
            raw_json = req.stream.read().decode('utf-8')
357
        except Exception as ex:
358
            print(str(ex))
359
            raise falcon.HTTPError(status=falcon.HTTP_400,
360
                                   title='API.BAD_REQUEST',
361
                                   description='API.FAILED_TO_READ_REQUEST_STREAM')
362
363
        new_values = json.loads(raw_json)
364
365
        if 'name' not in new_values['data'].keys() or \
366
                not isinstance(new_values['data']['name'], str) or \
367
                len(str.strip(new_values['data']['name'])) == 0:
368
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
369
                                   description='API.INVALID_ENERGY_FLOW_DIAGRAM_NAME')
370
        name = str.strip(new_values['data']['name'])
371
372
        cnx = mysql.connector.connect(**config.myems_system_db)
373
        cursor = cnx.cursor()
374
375
        cursor.execute(" SELECT name "
376
                       " FROM tbl_energy_flow_diagrams "
377
                       " WHERE id = %s ", (id_,))
378
        if cursor.fetchone() is None:
379
            cursor.close()
380
            cnx.close()
381
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
382
                                   description='API.ENERGY_FLOW_DIAGRAM_NOT_FOUND')
383
384
        cursor.execute(" SELECT name "
385
                       " FROM tbl_energy_flow_diagrams "
386
                       " WHERE name = %s AND id != %s ", (name, id_))
387
        if cursor.fetchone() is not None:
388
            cursor.close()
389
            cnx.close()
390
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
391
                                   description='API.ENERGY_FLOW_DIAGRAM_NAME_IS_ALREADY_IN_USE')
392
393
        update_row = (" UPDATE tbl_energy_flow_diagrams "
394
                      " SET name = %s "
395
                      " WHERE id = %s ")
396
        cursor.execute(update_row, (name,
397
                                    id_))
398
        cnx.commit()
399
400
        cursor.close()
401
        cnx.close()
402
403
        resp.status = falcon.HTTP_200
404
405
406
class EnergyFlowDiagramLinkCollection:
407
    def __init__(self):
408
        """"Initializes EnergyFlowDiagramLinkCollection"""
409
        pass
410
411
    @staticmethod
412
    def on_options(req, resp, id_):
413
        _ = req
414
        resp.status = falcon.HTTP_200
415
        _ = id_
416
417
    @staticmethod
418
    def on_get(req, resp, id_):
419
        if 'API-KEY' not in req.headers or \
420
                not isinstance(req.headers['API-KEY'], str) or \
421
                len(str.strip(req.headers['API-KEY'])) == 0:
422
            access_control(req)
423
        else:
424
            api_key_control(req)
425
        if not id_.isdigit() or int(id_) <= 0:
426
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
427
                                   description='API.INVALID_ENERGY_FLOW_DIAGRAM_ID')
428
429
        cnx = mysql.connector.connect(**config.myems_system_db)
430
        cursor = cnx.cursor()
431
432
        query = (" SELECT id, name "
433
                 " FROM tbl_energy_flow_diagrams_nodes ")
434
        cursor.execute(query)
435
        rows_nodes = cursor.fetchall()
436
437
        node_dict = dict()
438
        if rows_nodes is not None and len(rows_nodes) > 0:
439
            for row in rows_nodes:
440
                node_dict[row[0]] = {"id": row[0],
441
                                     "name": row[1]}
442
443
        query = (" SELECT id, name, uuid "
444
                 " FROM tbl_meters ")
445
        cursor.execute(query)
446
        rows_meters = cursor.fetchall()
447
448
        meter_dict = dict()
449
        if rows_meters is not None and len(rows_meters) > 0:
450
            for row in rows_meters:
451
                meter_dict[row[2]] = {"type": 'meter',
452
                                      "id": row[0],
453
                                      "name": row[1],
454
                                      "uuid": row[2]}
455
456
        query = (" SELECT id, name, uuid "
457
                 " FROM tbl_offline_meters ")
458
        cursor.execute(query)
459
        rows_offline_meters = cursor.fetchall()
460
461
        offline_meter_dict = dict()
462
        if rows_offline_meters is not None and len(rows_offline_meters) > 0:
463
            for row in rows_offline_meters:
464
                offline_meter_dict[row[2]] = {"type": 'offline_meter',
465
                                              "id": row[0],
466
                                              "name": row[1],
467
                                              "uuid": row[2]}
468
469
        query = (" SELECT id, name, uuid "
470
                 " FROM tbl_virtual_meters ")
471
        cursor.execute(query)
472
        rows_virtual_meters = cursor.fetchall()
473
474
        virtual_meter_dict = dict()
475
        if rows_virtual_meters is not None and len(rows_virtual_meters) > 0:
476
            for row in rows_virtual_meters:
477
                virtual_meter_dict[row[2]] = {"type": 'virtual_meter',
478
                                              "id": row[0],
479
                                              "name": row[1],
480
                                              "uuid": row[2]}
481
482
        cursor.execute(" SELECT name "
483
                       " FROM tbl_energy_flow_diagrams "
484
                       " WHERE id = %s ", (id_,))
485
        if cursor.fetchone() is None:
486
            cursor.close()
487
            cnx.close()
488
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
489
                                   description='API.ENERGY_FLOW_DIAGRAM_NOT_FOUND')
490
491
        query = (" SELECT id, source_node_id, target_node_id, meter_uuid "
492
                 " FROM tbl_energy_flow_diagrams_links "
493
                 " WHERE energy_flow_diagram_id = %s "
494
                 " ORDER BY id ")
495
        cursor.execute(query, (id_, ))
496
        rows_links = cursor.fetchall()
497
498
        result = list()
499
        if rows_links is not None and len(rows_links) > 0:
500
            for row in rows_links:
501
                source_node = node_dict.get(row[1], None)
502
                target_node = node_dict.get(row[2], None)
503
                # find meter by uuid
504
                meter = meter_dict.get(row[3], None)
505
                if meter is None:
506
                    meter = virtual_meter_dict.get(row[3], None)
507
                if meter is None:
508
                    meter = offline_meter_dict.get(row[3], None)
509
510
                meta_result = {"id": row[0],
511
                               "source_node": source_node,
512
                               "target_node": target_node,
513
                               "meter": meter}
514
                result.append(meta_result)
515
516
        cursor.close()
517
        cnx.close()
518
        resp.text = json.dumps(result)
519
520
    @staticmethod
521
    @user_logger
522
    def on_post(req, resp, id_):
523
        """Handles POST requests"""
524
        admin_control(req)
525
        if not id_.isdigit() or int(id_) <= 0:
526
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
527
                                   description='API.INVALID_ENERGY_FLOW_DIAGRAM_ID')
528
        try:
529
            raw_json = req.stream.read().decode('utf-8')
530
        except Exception as ex:
531
            print(str(ex))
532
            raise falcon.HTTPError(status=falcon.HTTP_400,
533
                                   title='API.BAD_REQUEST',
534
                                   description='API.FAILED_TO_READ_REQUEST_STREAM')
535
536
        new_values = json.loads(raw_json)
537
538
        source_node_id = None
539
        if 'source_node_id' in new_values['data'].keys():
540
            if new_values['data']['source_node_id'] is not None and \
541
                    new_values['data']['source_node_id'] <= 0:
542
                raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
543
                                       description='API.INVALID_SOURCE_NODE_ID')
544
            source_node_id = new_values['data']['source_node_id']
545
546
        target_node_id = None
547
        if 'target_node_id' in new_values['data'].keys():
548
            if new_values['data']['target_node_id'] is not None and \
549
                    new_values['data']['target_node_id'] <= 0:
550
                raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
551
                                       description='API.INVALID_TARGET_NODE_ID')
552
            target_node_id = new_values['data']['target_node_id']
553
554
        meter_uuid = None
555
        if 'meter_uuid' in new_values['data'].keys():
556
            if new_values['data']['meter_uuid'] is not None and \
557
                    isinstance(new_values['data']['meter_uuid'], str) and \
558
                    len(str.strip(new_values['data']['meter_uuid'])) > 0:
559
                meter_uuid = str.strip(new_values['data']['meter_uuid'])
560
561
        cnx = mysql.connector.connect(**config.myems_system_db)
562
        cursor = cnx.cursor()
563
564
        cursor.execute(" SELECT name "
565
                       " FROM tbl_energy_flow_diagrams "
566
                       " WHERE id = %s ", (id_,))
567
        if cursor.fetchone() is None:
568
            cursor.close()
569
            cnx.close()
570
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.NOT_FOUND',
571
                                   description='API.ENERGY_FLOW_DIAGRAM_NOT_FOUND')
572
573
        cursor.execute(" SELECT id "
574
                       " FROM tbl_energy_flow_diagrams_links "
575
                       " WHERE energy_flow_diagram_id = %s AND "
576
                       "       source_node_id = %s AND target_node_id = %s ",
577
                       (id_, source_node_id, target_node_id,))
578
        row = cursor.fetchone()
579
        if row is not None:
580
            cursor.close()
581
            cnx.close()
582
            raise falcon.HTTPError(status=falcon.HTTP_400,
583
                                   title='API.NOT_FOUND',
584
                                   description='API.ENERGY_FLOW_DIAGRAM_LINK_IS_ALREADY_IN_USE')
585
586
        query = (" SELECT id, name "
587
                 " FROM tbl_energy_flow_diagrams_nodes "
588
                 " WHERE id = %s ")
589
        cursor.execute(query, (source_node_id,))
590
        if cursor.fetchone() is None:
591
            cursor.close()
592
            cnx.close()
593
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
594
                                   description='API.SOURCE_NODE_NOT_FOUND')
595
596
        query = (" SELECT id, name "
597
                 " FROM tbl_energy_flow_diagrams_nodes "
598
                 " WHERE id = %s ")
599
        cursor.execute(query, (target_node_id,))
600
        if cursor.fetchone() is None:
601
            cursor.close()
602
            cnx.close()
603
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
604
                                   description='API.TARGET_NODE_NOT_FOUND')
605
606
        query = (" SELECT id, name, uuid "
607
                 " FROM tbl_meters ")
608
        cursor.execute(query)
609
        rows_meters = cursor.fetchall()
610
611
        meter_dict = dict()
612
        if rows_meters is not None and len(rows_meters) > 0:
613
            for row in rows_meters:
614
                meter_dict[row[2]] = {"type": 'meter',
615
                                      "id": row[0],
616
                                      "name": row[1],
617
                                      "uuid": row[2]}
618
619
        query = (" SELECT id, name, uuid "
620
                 " FROM tbl_offline_meters ")
621
        cursor.execute(query)
622
        rows_offline_meters = cursor.fetchall()
623
624
        offline_meter_dict = dict()
625
        if rows_offline_meters is not None and len(rows_offline_meters) > 0:
626
            for row in rows_offline_meters:
627
                offline_meter_dict[row[2]] = {"type": 'offline_meter',
628
                                              "id": row[0],
629
                                              "name": row[1],
630
                                              "uuid": row[2]}
631
632
        query = (" SELECT id, name, uuid "
633
                 " FROM tbl_virtual_meters ")
634
        cursor.execute(query)
635
        rows_virtual_meters = cursor.fetchall()
636
637
        virtual_meter_dict = dict()
638
        if rows_virtual_meters is not None and len(rows_virtual_meters) > 0:
639
            for row in rows_virtual_meters:
640
                virtual_meter_dict[row[2]] = {"type": 'virtual_meter',
641
                                              "id": row[0],
642
                                              "name": row[1],
643
                                              "uuid": row[2]}
644
645
        # validate meter uuid
646
        if meter_dict.get(meter_uuid) is None and \
647
                virtual_meter_dict.get(meter_uuid) is None and \
648
                offline_meter_dict.get(meter_uuid) is None:
649
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
650
                                   description='API.INVALID_METER_UUID')
651
652
        add_values = (" INSERT INTO tbl_energy_flow_diagrams_links "
653
                      "    (energy_flow_diagram_id, source_node_id, target_node_id, meter_uuid) "
654
                      " VALUES (%s, %s, %s, %s) ")
655
        cursor.execute(add_values, (id_,
656
                                    source_node_id,
657
                                    target_node_id,
658
                                    meter_uuid))
659
        new_id = cursor.lastrowid
660
        cnx.commit()
661
        cursor.close()
662
        cnx.close()
663
664
        resp.status = falcon.HTTP_201
665
        resp.location = '/energyflowdiagrams/' + str(id_) + 'links/' + str(new_id)
666
667
668
class EnergyFlowDiagramLinkItem:
669
    def __init__(self):
670
        """"Initializes EnergyFlowDiagramLinkItem"""
671
        pass
672
673
    @staticmethod
674
    def on_options(req, resp, id_, lid):
675
        _ = req
676
        resp.status = falcon.HTTP_200
677
        _ = id_
678
679
    @staticmethod
680
    def on_get(req, resp, id_, lid):
681
        access_control(req)
682
        if not id_.isdigit() or int(id_) <= 0:
683
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
684
                                   description='API.INVALID_ENERGY_FLOW_DIAGRAM_ID')
685
686
        if not lid.isdigit() or int(lid) <= 0:
687
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
688
                                   description='API.INVALID_ENERGY_FLOW_DIAGRAM_LINK_ID')
689
690
        cnx = mysql.connector.connect(**config.myems_system_db)
691
        cursor = cnx.cursor()
692
693
        query = (" SELECT id, name "
694
                 " FROM tbl_energy_flow_diagrams_nodes ")
695
        cursor.execute(query)
696
        rows_nodes = cursor.fetchall()
697
698
        node_dict = dict()
699
        if rows_nodes is not None and len(rows_nodes) > 0:
700
            for row in rows_nodes:
701
                node_dict[row[0]] = {"id": row[0],
702
                                     "name": row[1]}
703
704
        query = (" SELECT id, name, uuid "
705
                 " FROM tbl_meters ")
706
        cursor.execute(query)
707
        rows_meters = cursor.fetchall()
708
709
        meter_dict = dict()
710
        if rows_meters is not None and len(rows_meters) > 0:
711
            for row in rows_meters:
712
                meter_dict[row[2]] = {"type": 'meter',
713
                                      "id": row[0],
714
                                      "name": row[1],
715
                                      "uuid": row[2]}
716
717
        query = (" SELECT id, name, uuid "
718
                 " FROM tbl_offline_meters ")
719
        cursor.execute(query)
720
        rows_offline_meters = cursor.fetchall()
721
722
        offline_meter_dict = dict()
723
        if rows_offline_meters is not None and len(rows_offline_meters) > 0:
724
            for row in rows_offline_meters:
725
                offline_meter_dict[row[2]] = {"type": 'offline_meter',
726
                                              "id": row[0],
727
                                              "name": row[1],
728
                                              "uuid": row[2]}
729
730
        query = (" SELECT id, name, uuid "
731
                 " FROM tbl_virtual_meters ")
732
        cursor.execute(query)
733
        rows_virtual_meters = cursor.fetchall()
734
735
        virtual_meter_dict = dict()
736
        if rows_virtual_meters is not None and len(rows_virtual_meters) > 0:
737
            for row in rows_virtual_meters:
738
                virtual_meter_dict[row[2]] = {"type": 'virtual_meter',
739
                                              "id": row[0],
740
                                              "name": row[1],
741
                                              "uuid": row[2]}
742
743
        query = (" SELECT id, source_node_id, target_node_id, meter_uuid "
744
                 " FROM tbl_energy_flow_diagrams_links "
745
                 " WHERE energy_flow_diagram_id = %s AND id = %s ")
746
        cursor.execute(query, (id_, lid))
747
        row = cursor.fetchone()
748
        cursor.close()
749
        cnx.close()
750
751
        if row is None:
752
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
753
                                   description='API.ENERGY_FLOW_DIAGRAM_LINK_NOT_FOUND_OR_NOT_MATCH')
754
        else:
755
            source_node = node_dict.get(row[1], None)
756
            target_node = node_dict.get(row[2], None)
757
            # find meter by uuid
758
            meter = meter_dict.get(row[3], None)
759
            if meter is None:
760
                meter = virtual_meter_dict.get(row[3], None)
761
            if meter is None:
762
                meter = offline_meter_dict.get(row[3], None)
763
764
            meta_result = {"id": row[0],
765
                           "source_node": source_node,
766
                           "target_node": target_node,
767
                           "meter": meter}
768
            resp.text = json.dumps(meta_result)
769
770
    @staticmethod
771
    @user_logger
772
    def on_delete(req, resp, id_, lid):
773
        admin_control(req)
774
        if not id_.isdigit() or int(id_) <= 0:
775
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
776
                                   description='API.INVALID_ENERGY_FLOW_DIAGRAM_ID')
777
778
        if not lid.isdigit() or int(lid) <= 0:
779
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
780
                                   description='API.INVALID_ENERGY_FLOW_DIAGRAM_LINK_ID')
781
782
        cnx = mysql.connector.connect(**config.myems_system_db)
783
        cursor = cnx.cursor()
784
785
        cursor.execute(" SELECT name "
786
                       " FROM tbl_energy_flow_diagrams "
787
                       " WHERE id = %s ",
788
                       (id_,))
789
        row = cursor.fetchone()
790
        if row is None:
791
            cursor.close()
792
            cnx.close()
793
            raise falcon.HTTPError(status=falcon.HTTP_400,
794
                                   title='API.NOT_FOUND',
795
                                   description='API.ENERGY_FLOW_DIAGRAM_NOT_FOUND')
796
797
        cursor.execute(" SELECT id "
798
                       " FROM tbl_energy_flow_diagrams_links "
799
                       " WHERE energy_flow_diagram_id = %s AND id = %s ",
800
                       (id_, lid,))
801
        row = cursor.fetchone()
802
        if row is None:
803
            cursor.close()
804
            cnx.close()
805
            raise falcon.HTTPError(status=falcon.HTTP_400,
806
                                   title='API.NOT_FOUND',
807
                                   description='API.ENERGY_FLOW_DIAGRAM_LINK_NOT_FOUND_OR_NOT_MATCH')
808
809
        cursor.execute(" DELETE FROM tbl_energy_flow_diagrams_links "
810
                       " WHERE id = %s ", (lid, ))
811
        cnx.commit()
812
813
        cursor.close()
814
        cnx.close()
815
816
        resp.status = falcon.HTTP_204
817
818
    @staticmethod
819
    @user_logger
820
    def on_put(req, resp, id_, lid):
821
        """Handles PUT requests"""
822
        admin_control(req)
823
        if not id_.isdigit() or int(id_) <= 0:
824
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
825
                                   description='API.INVALID_ENERGY_FLOW_DIAGRAM_ID')
826
827
        if not lid.isdigit() or int(lid) <= 0:
828
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
829
                                   description='API.INVALID_ENERGY_FLOW_DIAGRAM_LINK_ID')
830
831
        try:
832
            raw_json = req.stream.read().decode('utf-8')
833
        except Exception as ex:
834
            print(str(ex))
835
            raise falcon.HTTPError(status=falcon.HTTP_400,
836
                                   title='API.BAD_REQUEST',
837
                                   description='API.FAILED_TO_READ_REQUEST_STREAM')
838
839
        new_values = json.loads(raw_json)
840
841
        source_node_id = None
842
        if 'source_node_id' in new_values['data'].keys():
843
            if new_values['data']['source_node_id'] is not None and \
844
                    new_values['data']['source_node_id'] <= 0:
845
                raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
846
                                       description='API.INVALID_SOURCE_NODE_ID')
847
            source_node_id = new_values['data']['source_node_id']
848
849
        target_node_id = None
850
        if 'target_node_id' in new_values['data'].keys():
851
            if new_values['data']['target_node_id'] is not None and \
852
                    new_values['data']['target_node_id'] <= 0:
853
                raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
854
                                       description='API.INVALID_TARGET_NODE_ID')
855
            target_node_id = new_values['data']['target_node_id']
856
857
        meter_uuid = None
858
        if 'meter_uuid' in new_values['data'].keys():
859
            if new_values['data']['meter_uuid'] is not None and \
860
                    isinstance(new_values['data']['meter_uuid'], str) and \
861
                    len(str.strip(new_values['data']['meter_uuid'])) > 0:
862
                meter_uuid = str.strip(new_values['data']['meter_uuid'])
863
864
        cnx = mysql.connector.connect(**config.myems_system_db)
865
        cursor = cnx.cursor()
866
867
        cursor.execute(" SELECT name "
868
                       " FROM tbl_energy_flow_diagrams "
869
                       " WHERE id = %s ", (id_,))
870
        if cursor.fetchone() is None:
871
            cursor.close()
872
            cnx.close()
873
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.NOT_FOUND',
874
                                   description='API.ENERGY_FLOW_DIAGRAM_NOT_FOUND')
875
876
        cursor.execute(" SELECT id "
877
                       " FROM tbl_energy_flow_diagrams_links "
878
                       " WHERE energy_flow_diagram_id = %s AND id = %s ",
879
                       (id_, lid,))
880
        row = cursor.fetchone()
881
        if row is None:
882
            cursor.close()
883
            cnx.close()
884
            raise falcon.HTTPError(status=falcon.HTTP_400,
885
                                   title='API.NOT_FOUND',
886
                                   description='API.ENERGY_FLOW_DIAGRAM_LINK_NOT_FOUND_OR_NOT_MATCH')
887
888
        cursor.execute(" SELECT id "
889
                       " FROM tbl_energy_flow_diagrams_links "
890
                       " WHERE energy_flow_diagram_id = %s AND id != %s "
891
                       "       AND source_node_id = %s AND target_node_id = %s ",
892
                       (id_, lid, source_node_id, target_node_id,))
893
        row = cursor.fetchone()
894
        if row is not None:
895
            cursor.close()
896
            cnx.close()
897
            raise falcon.HTTPError(status=falcon.HTTP_400,
898
                                   title='API.NOT_FOUND',
899
                                   description='API.ENERGY_FLOW_DIAGRAM_LINK_IS_ALREADY_IN_USE')
900
901
        query = (" SELECT id, name "
902
                 " FROM tbl_energy_flow_diagrams_nodes "
903
                 " WHERE id = %s ")
904
        cursor.execute(query, (source_node_id,))
905
        if cursor.fetchone() is None:
906
            cursor.close()
907
            cnx.close()
908
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
909
                                   description='API.SOURCE_NODE_NOT_FOUND')
910
911
        query = (" SELECT id, name "
912
                 " FROM tbl_energy_flow_diagrams_nodes "
913
                 " WHERE id = %s ")
914
        cursor.execute(query, (target_node_id,))
915
        if cursor.fetchone() is None:
916
            cursor.close()
917
            cnx.close()
918
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
919
                                   description='API.TARGET_NODE_NOT_FOUND')
920
921
        query = (" SELECT id, name, uuid "
922
                 " FROM tbl_meters ")
923
        cursor.execute(query)
924
        rows_meters = cursor.fetchall()
925
926
        meter_dict = dict()
927
        if rows_meters is not None and len(rows_meters) > 0:
928
            for row in rows_meters:
929
                meter_dict[row[2]] = {"type": 'meter',
930
                                      "id": row[0],
931
                                      "name": row[1],
932
                                      "uuid": row[2]}
933
934
        query = (" SELECT id, name, uuid "
935
                 " FROM tbl_offline_meters ")
936
        cursor.execute(query)
937
        rows_offline_meters = cursor.fetchall()
938
939
        offline_meter_dict = dict()
940
        if rows_offline_meters is not None and len(rows_offline_meters) > 0:
941
            for row in rows_offline_meters:
942
                offline_meter_dict[row[2]] = {"type": 'offline_meter',
943
                                              "id": row[0],
944
                                              "name": row[1],
945
                                              "uuid": row[2]}
946
947
        query = (" SELECT id, name, uuid "
948
                 " FROM tbl_virtual_meters ")
949
        cursor.execute(query)
950
        rows_virtual_meters = cursor.fetchall()
951
952
        virtual_meter_dict = dict()
953
        if rows_virtual_meters is not None and len(rows_virtual_meters) > 0:
954
            for row in rows_virtual_meters:
955
                virtual_meter_dict[row[2]] = {"type": 'virtual_meter',
956
                                              "id": row[0],
957
                                              "name": row[1],
958
                                              "uuid": row[2]}
959
960
        # validate meter uuid
961
        if meter_dict.get(meter_uuid) is None and \
962
                virtual_meter_dict.get(meter_uuid) is None and \
963
                offline_meter_dict.get(meter_uuid) is None:
964
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
965
                                   description='API.INVALID_METER_UUID')
966
967
        add_values = (" UPDATE tbl_energy_flow_diagrams_links "
968
                      " SET source_node_id = %s, target_node_id = %s, meter_uuid = %s "
969
                      " WHERE id = %s ")
970
        cursor.execute(add_values, (source_node_id,
971
                                    target_node_id,
972
                                    meter_uuid,
973
                                    lid))
974
        cnx.commit()
975
976
        cursor.close()
977
        cnx.close()
978
979
        resp.status = falcon.HTTP_200
980
981
982
class EnergyFlowDiagramNodeCollection:
983
    def __init__(self):
984
        """"Initializes EnergyFlowDiagramNodeCollection"""
985
        pass
986
987
    @staticmethod
988
    def on_options(req, resp, id_):
989
        _ = req
990
        resp.status = falcon.HTTP_200
991
        _ = id_
992
993
    @staticmethod
994
    def on_get(req, resp, id_):
995
        if 'API-KEY' not in req.headers or \
996
                not isinstance(req.headers['API-KEY'], str) or \
997
                len(str.strip(req.headers['API-KEY'])) == 0:
998
            access_control(req)
999
        else:
1000
            api_key_control(req)
1001
        if not id_.isdigit() or int(id_) <= 0:
1002
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
1003
                                   description='API.INVALID_ENERGY_FLOW_DIAGRAM_ID')
1004
1005
        cnx = mysql.connector.connect(**config.myems_system_db)
1006
        cursor = cnx.cursor()
1007
1008
        cursor.execute(" SELECT name "
1009
                       " FROM tbl_energy_flow_diagrams "
1010
                       " WHERE id = %s ", (id_,))
1011
        if cursor.fetchone() is None:
1012
            cursor.close()
1013
            cnx.close()
1014
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
1015
                                   description='API.ENERGY_FLOW_DIAGRAM_NOT_FOUND')
1016
1017
        query = (" SELECT id, name "
1018
                 " FROM tbl_energy_flow_diagrams_nodes "
1019
                 " WHERE energy_flow_diagram_id = %s "
1020
                 " ORDER BY id ")
1021
        cursor.execute(query, (id_, ))
1022
        rows_nodes = cursor.fetchall()
1023
1024
        result = list()
1025
        if rows_nodes is not None and len(rows_nodes) > 0:
1026
            for row in rows_nodes:
1027
                meta_result = {"id": row[0],
1028
                               "name": row[1]}
1029
                result.append(meta_result)
1030
1031
        cursor.close()
1032
        cnx.close()
1033
        resp.text = json.dumps(result)
1034
1035
    @staticmethod
1036
    @user_logger
1037
    def on_post(req, resp, id_):
1038
        """Handles POST requests"""
1039
        admin_control(req)
1040
        if not id_.isdigit() or int(id_) <= 0:
1041
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
1042
                                   description='API.INVALID_ENERGY_FLOW_DIAGRAM_ID')
1043
        try:
1044
            raw_json = req.stream.read().decode('utf-8')
1045
        except Exception as ex:
1046
            print(str(ex))
1047
            raise falcon.HTTPError(status=falcon.HTTP_400,
1048
                                   title='API.BAD_REQUEST',
1049
                                   description='API.FAILED_TO_READ_REQUEST_STREAM')
1050
1051
        new_values = json.loads(raw_json)
1052
1053
        if 'name' not in new_values['data'].keys() or \
1054
                not isinstance(new_values['data']['name'], str) or \
1055
                len(str.strip(new_values['data']['name'])) == 0:
1056
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
1057
                                   description='API.INVALID_ENERGY_FLOW_DIAGRAM_NODE_NAME')
1058
        name = str.strip(new_values['data']['name'])
1059
1060
        cnx = mysql.connector.connect(**config.myems_system_db)
1061
        cursor = cnx.cursor()
1062
1063
        cursor.execute(" SELECT name "
1064
                       " FROM tbl_energy_flow_diagrams "
1065
                       " WHERE id = %s ", (id_,))
1066
        if cursor.fetchone() is None:
1067
            cursor.close()
1068
            cnx.close()
1069
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.NOT_FOUND',
1070
                                   description='API.ENERGY_FLOW_DIAGRAM_NOT_FOUND')
1071
1072
        cursor.execute(" SELECT name "
1073
                       " FROM tbl_energy_flow_diagrams_nodes "
1074
                       " WHERE name = %s AND energy_flow_diagram_id = %s ", (name, id_))
1075
        if cursor.fetchone() is not None:
1076
            cursor.close()
1077
            cnx.close()
1078
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
1079
                                   description='API.ENERGY_FLOW_DIAGRAM_NAME_IS_ALREADY_IN_USE')
1080
1081
        add_values = (" INSERT INTO tbl_energy_flow_diagrams_nodes "
1082
                      "    (energy_flow_diagram_id, name) "
1083
                      " VALUES (%s, %s) ")
1084
        cursor.execute(add_values, (id_,
1085
                                    name))
1086
        new_id = cursor.lastrowid
1087
        cnx.commit()
1088
        cursor.close()
1089
        cnx.close()
1090
1091
        resp.status = falcon.HTTP_201
1092
        resp.location = '/energyflowdiagrams/' + str(id_) + 'nodes/' + str(new_id)
1093
1094
1095
class EnergyFlowDiagramNodeItem:
1096
    def __init__(self):
1097
        """"Initializes EnergyFlowDiagramNodeItem"""
1098
        pass
1099
1100
    @staticmethod
1101
    def on_options(req, resp, id_, nid):
1102
        _ = req
1103
        resp.status = falcon.HTTP_200
1104
        _ = id_
1105
1106
    @staticmethod
1107
    def on_get(req, resp, id_, nid):
1108
        access_control(req)
1109
        if not id_.isdigit() or int(id_) <= 0:
1110
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
1111
                                   description='API.INVALID_ENERGY_FLOW_DIAGRAM_ID')
1112
1113
        if not nid.isdigit() or int(nid) <= 0:
1114
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
1115
                                   description='API.INVALID_ENERGY_FLOW_DIAGRAM_NODE_ID')
1116
1117
        cnx = mysql.connector.connect(**config.myems_system_db)
1118
        cursor = cnx.cursor()
1119
1120
        query = (" SELECT id, name "
1121
                 " FROM tbl_energy_flow_diagrams_nodes "
1122
                 " WHERE energy_flow_diagram_id = %s AND id = %s ")
1123
        cursor.execute(query, (id_, nid))
1124
        row = cursor.fetchone()
1125
        cursor.close()
1126
        cnx.close()
1127
1128
        if row is None:
1129
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
1130
                                   description='API.ENERGY_FLOW_DIAGRAM_NODE_NOT_FOUND_OR_NOT_MATCH')
1131
        else:
1132
            meta_result = {"id": row[0],
1133
                           "name": row[1]}
1134
1135
        resp.text = json.dumps(meta_result)
1136
1137
    @staticmethod
1138
    @user_logger
1139
    def on_delete(req, resp, id_, nid):
1140
        admin_control(req)
1141
        if not id_.isdigit() or int(id_) <= 0:
1142
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
1143
                                   description='API.INVALID_ENERGY_FLOW_DIAGRAM_ID')
1144
1145
        if not nid.isdigit() or int(nid) <= 0:
1146
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
1147
                                   description='API.INVALID_ENERGY_FLOW_DIAGRAM_NODE_ID')
1148
1149
        cnx = mysql.connector.connect(**config.myems_system_db)
1150
        cursor = cnx.cursor()
1151
1152
        cursor.execute(" SELECT name "
1153
                       " FROM tbl_energy_flow_diagrams "
1154
                       " WHERE id = %s ",
1155
                       (id_,))
1156
        row = cursor.fetchone()
1157
        if row is None:
1158
            cursor.close()
1159
            cnx.close()
1160
            raise falcon.HTTPError(status=falcon.HTTP_400,
1161
                                   title='API.NOT_FOUND',
1162
                                   description='API.ENERGY_FLOW_DIAGRAM_NOT_FOUND')
1163
1164
        cursor.execute(" SELECT name "
1165
                       " FROM tbl_energy_flow_diagrams_nodes "
1166
                       " WHERE energy_flow_diagram_id = %s AND id = %s ",
1167
                       (id_, nid,))
1168
        row = cursor.fetchone()
1169
        if row is None:
1170
            cursor.close()
1171
            cnx.close()
1172
            raise falcon.HTTPError(status=falcon.HTTP_400,
1173
                                   title='API.NOT_FOUND',
1174
                                   description='API.ENERGY_FLOW_DIAGRAM_NODE_NOT_FOUND_OR_NOT_MATCH')
1175
1176
        # check relation with links
1177
        cursor.execute(" SELECT id "
1178
                       " FROM tbl_energy_flow_diagrams_links "
1179
                       " WHERE energy_flow_diagram_id = %s AND "
1180
                       " (source_node_id = %s OR target_node_id = %s) ", (id_, nid, nid))
1181
        rows_links = cursor.fetchall()
1182
        if rows_links is not None and len(rows_links) > 0:
1183
            cursor.close()
1184
            cnx.close()
1185
            raise falcon.HTTPError(status=falcon.HTTP_400,
1186
                                   title='API.BAD_REQUEST',
1187
                                   description='API.THERE_IS_RELATION_WITH_LINKS')
1188
1189
        cursor.execute(" DELETE FROM tbl_energy_flow_diagrams_nodes "
1190
                       " WHERE id = %s ", (nid, ))
1191
        cnx.commit()
1192
1193
        cursor.close()
1194
        cnx.close()
1195
1196
        resp.status = falcon.HTTP_204
1197
1198
    @staticmethod
1199
    @user_logger
1200
    def on_put(req, resp, id_, nid):
1201
        """Handles PUT requests"""
1202
        admin_control(req)
1203
        if not id_.isdigit() or int(id_) <= 0:
1204
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
1205
                                   description='API.INVALID_ENERGY_FLOW_DIAGRAM_ID')
1206
1207
        if not nid.isdigit() or int(nid) <= 0:
1208
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
1209
                                   description='API.INVALID_ENERGY_FLOW_DIAGRAM_NODE_ID')
1210
1211
        try:
1212
            raw_json = req.stream.read().decode('utf-8')
1213
        except Exception as ex:
1214
            print(str(ex))
1215
            raise falcon.HTTPError(status=falcon.HTTP_400,
1216
                                   title='API.BAD_REQUEST',
1217
                                   description='API.FAILED_TO_READ_REQUEST_STREAM')
1218
1219
        new_values = json.loads(raw_json)
1220
1221
        if 'name' not in new_values['data'].keys() or \
1222
                not isinstance(new_values['data']['name'], str) or \
1223
                len(str.strip(new_values['data']['name'])) == 0:
1224
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
1225
                                   description='API.INVALID_ENERGY_FLOW_DIAGRAM_NODE_NAME')
1226
        name = str.strip(new_values['data']['name'])
1227
1228
        cnx = mysql.connector.connect(**config.myems_system_db)
1229
        cursor = cnx.cursor()
1230
1231
        cursor.execute(" SELECT name "
1232
                       " FROM tbl_energy_flow_diagrams "
1233
                       " WHERE id = %s ", (id_,))
1234
        if cursor.fetchone() is None:
1235
            cursor.close()
1236
            cnx.close()
1237
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.NOT_FOUND',
1238
                                   description='API.ENERGY_FLOW_DIAGRAM_NOT_FOUND')
1239
1240
        cursor.execute(" SELECT name "
1241
                       " FROM tbl_energy_flow_diagrams_nodes "
1242
                       " WHERE energy_flow_diagram_id = %s AND id = %s ",
1243
                       (id_, nid,))
1244
        row = cursor.fetchone()
1245
        if row is None:
1246
            cursor.close()
1247
            cnx.close()
1248
            raise falcon.HTTPError(status=falcon.HTTP_400,
1249
                                   title='API.NOT_FOUND',
1250
                                   description='API.ENERGY_FLOW_DIAGRAM_NODE_NOT_FOUND_OR_NOT_MATCH')
1251
1252
        cursor.execute(" SELECT name "
1253
                       " FROM tbl_energy_flow_diagrams_nodes "
1254
                       " WHERE name = %s AND energy_flow_diagram_id = %s  AND id != %s ", (name, id_, nid))
1255
        row = cursor.fetchone()
1256
        if row is not None:
1257
            cursor.close()
1258
            cnx.close()
1259
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
1260
                                   description='API.ENERGY_FLOW_DIAGRAM_NODE_NAME_IS_ALREADY_IN_USE')
1261
1262
        add_values = (" UPDATE tbl_energy_flow_diagrams_nodes "
1263
                      " SET name = %s "
1264
                      " WHERE id = %s ")
1265
        cursor.execute(add_values, (name,
1266
                                    nid))
1267
        cnx.commit()
1268
1269
        cursor.close()
1270
        cnx.close()
1271
1272
        resp.status = falcon.HTTP_200
1273
1274
1275
class EnergyFlowDiagramExport:
1276
    def __init__(self):
1277
        """"Initializes EnergyFlowDiagramExport"""
1278
        pass
1279
1280
    @staticmethod
1281
    def on_options(req, resp, id_):
1282
        _ = req
1283
        resp.status = falcon.HTTP_200
1284
        _ = id_
1285
1286 View Code Duplication
    @staticmethod
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
1287
    def on_get(req, resp, id_):
1288
        if 'API-KEY' not in req.headers or \
1289
                not isinstance(req.headers['API-KEY'], str) or \
1290
                len(str.strip(req.headers['API-KEY'])) == 0:
1291
            access_control(req)
1292
        else:
1293
            api_key_control(req)
1294
        if not id_.isdigit() or int(id_) <= 0:
1295
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
1296
                                   description='API.INVALID_ENERGY_FLOW_DIAGRAM_ID')
1297
1298
        cnx = mysql.connector.connect(**config.myems_system_db)
1299
        cursor = cnx.cursor()
1300
1301
        query = (" SELECT id, name, uuid "
1302
                 " FROM tbl_meters ")
1303
        cursor.execute(query)
1304
        rows_meters = cursor.fetchall()
1305
1306
        meter_dict = dict()
1307
        if rows_meters is not None and len(rows_meters) > 0:
1308
            for row in rows_meters:
1309
                meter_dict[row[2]] = {"type": 'meter',
1310
                                      "id": row[0],
1311
                                      "name": row[1],
1312
                                      "uuid": row[2]}
1313
1314
        query = (" SELECT id, name, uuid "
1315
                 " FROM tbl_offline_meters ")
1316
        cursor.execute(query)
1317
        rows_offline_meters = cursor.fetchall()
1318
1319
        offline_meter_dict = dict()
1320
        if rows_offline_meters is not None and len(rows_offline_meters) > 0:
1321
            for row in rows_offline_meters:
1322
                offline_meter_dict[row[2]] = {"type": 'offline_meter',
1323
                                              "id": row[0],
1324
                                              "name": row[1],
1325
                                              "uuid": row[2]}
1326
1327
        query = (" SELECT id, name, uuid "
1328
                 " FROM tbl_virtual_meters ")
1329
        cursor.execute(query)
1330
        rows_virtual_meters = cursor.fetchall()
1331
1332
        virtual_meter_dict = dict()
1333
        if rows_virtual_meters is not None and len(rows_virtual_meters) > 0:
1334
            for row in rows_virtual_meters:
1335
                virtual_meter_dict[row[2]] = {"type": 'virtual_meter',
1336
                                              "id": row[0],
1337
                                              "name": row[1],
1338
                                              "uuid": row[2]}
1339
1340
        query = (" SELECT id, energy_flow_diagram_id, name "
1341
                 " FROM tbl_energy_flow_diagrams_nodes")
1342
        cursor.execute(query)
1343
        rows_nodes = cursor.fetchall()
1344
1345
        node_dict = dict()
1346
        node_list_dict = dict()
1347
        if rows_nodes is not None and len(rows_nodes) > 0:
1348
            for row in rows_nodes:
1349
                node_dict[row[0]] = row[2]
1350
                if node_list_dict.get(row[1]) is None:
1351
                    node_list_dict[row[1]] = list()
1352
                node_list_dict[row[1]].append({"id": row[0], "name": row[2]})
1353
1354
        query = (" SELECT id, energy_flow_diagram_id, source_node_id, target_node_id, meter_uuid "
1355
                 " FROM tbl_energy_flow_diagrams_links")
1356
        cursor.execute(query)
1357
        rows_links = cursor.fetchall()
1358
1359
        link_list_dict = dict()
1360
        if rows_links is not None and len(rows_links) > 0:
1361
            for row in rows_links:
1362
                # find meter by uuid
1363
                meter = meter_dict.get(row[4], None)
1364
                if meter is None:
1365
                    meter = virtual_meter_dict.get(row[4], None)
1366
                if meter is None:
1367
                    meter = offline_meter_dict.get(row[4], None)
1368
1369
                if link_list_dict.get(row[1]) is None:
1370
                    link_list_dict[row[1]] = list()
1371
                link_list_dict[row[1]].append({"id": row[0],
1372
                                               "source_node": {
1373
                                                   "id": row[2],
1374
                                                   "name": node_dict.get(row[2])},
1375
                                               "target_node": {
1376
                                                   "id": row[3],
1377
                                                   "name": node_dict.get(row[3])},
1378
                                               "meter": meter})
1379
1380
        query = (" SELECT id, name, uuid "
1381
                 " FROM tbl_energy_flow_diagrams "
1382
                 " WHERE id = %s ")
1383
        cursor.execute(query, (id_,))
1384
        row = cursor.fetchone()
1385
        cursor.close()
1386
        cnx.close()
1387
1388
        if row is None:
1389
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
1390
                                   description='API.ENERGY_FLOW_DIAGRAM_NOT_FOUND')
1391
        else:
1392
            meta_result = {"id": row[0],
1393
                           "name": row[1],
1394
                           "uuid": row[2],
1395
                           "nodes": node_list_dict.get(row[0], None),
1396
                           "links": link_list_dict.get(row[0], None),
1397
                           }
1398
1399
        resp.text = json.dumps(meta_result)
1400
1401
1402
class EnergyFlowDiagramImport:
1403
    def __init__(self):
1404
        """"Initializes EnergyFlowDiagramImport"""
1405
        pass
1406
1407
    @staticmethod
1408
    def on_options(req, resp):
1409
        _ = req
1410
        resp.status = falcon.HTTP_200
1411
1412
    @staticmethod
1413
    @user_logger
1414
    def on_post(req, resp):
1415
        """Handles POST requests"""
1416
        admin_control(req)
1417
        try:
1418
            raw_json = req.stream.read().decode('utf-8')
1419
        except Exception as ex:
1420
            print(str(ex))
1421
            raise falcon.HTTPError(status=falcon.HTTP_400,
1422
                                   title='API.BAD_REQUEST',
1423
                                   description='API.FAILED_TO_READ_REQUEST_STREAM')
1424
1425
        new_values = json.loads(raw_json)
1426
1427
        if 'name' not in new_values.keys() or \
1428
                not isinstance(new_values['name'], str) or \
1429
                len(str.strip(new_values['name'])) == 0:
1430
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
1431
                                   description='API.INVALID_ENERGY_FLOW_DIAGRAM_NAME')
1432
        name = str.strip(new_values['name'])
1433
1434
        cnx = mysql.connector.connect(**config.myems_system_db)
1435
        cursor = cnx.cursor()
1436
1437
        cursor.execute(" SELECT name "
1438
                       " FROM tbl_energy_flow_diagrams "
1439
                       " WHERE name = %s ", (name,))
1440
        if cursor.fetchone() is not None:
1441
            cursor.close()
1442
            cnx.close()
1443
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
1444
                                   description='API.ENERGY_FLOW_DIAGRAM_NAME_IS_ALREADY_IN_USE')
1445
1446
        add_values = (" INSERT INTO tbl_energy_flow_diagrams "
1447
                      "    (name, uuid) "
1448
                      " VALUES (%s, %s) ")
1449
        cursor.execute(add_values, (name,
1450
                                    str(uuid.uuid4())))
1451
        new_id = cursor.lastrowid
1452
        for node in new_values['nodes']:
1453
            if 'name' not in node.keys() or \
1454
                    not isinstance(node['name'], str) or \
1455
                    len(str.strip(node['name'])) == 0:
1456
                raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
1457
                                       description='API.INVALID_ENERGY_FLOW_DIAGRAM_NODE_NAME')
1458
            name = str.strip(node['name'])
1459
1460
            cursor.execute(" SELECT name "
1461
                           " FROM tbl_energy_flow_diagrams "
1462
                           " WHERE id = %s ", (new_id,))
1463
            if cursor.fetchone() is None:
1464
                cursor.close()
1465
                cnx.close()
1466
                raise falcon.HTTPError(status=falcon.HTTP_400, title='API.NOT_FOUND',
1467
                                       description='API.ENERGY_FLOW_DIAGRAM_NOT_FOUND')
1468
1469
            cursor.execute(" SELECT name "
1470
                           " FROM tbl_energy_flow_diagrams_nodes "
1471
                           " WHERE name = %s AND energy_flow_diagram_id = %s ", (name, new_id))
1472
            if cursor.fetchone() is not None:
1473
                cursor.close()
1474
                cnx.close()
1475
                raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
1476
                                       description='API.ENERGY_FLOW_DIAGRAM_NAME_IS_ALREADY_IN_USE')
1477
1478
            add_values = (" INSERT INTO tbl_energy_flow_diagrams_nodes "
1479
                          "    (energy_flow_diagram_id, name) "
1480
                          " VALUES (%s, %s) ")
1481
            cursor.execute(add_values, (new_id,
1482
                                        name))
1483
        for link in new_values['links']:
1484
            source_node_id = None
1485
            if 'id' in link['source_node'].keys():
1486
                if link['source_node']['id'] is not None and \
1487
                        link['source_node']['id'] <= 0:
1488
                    raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
1489
                                           description='API.INVALID_SOURCE_NODE_ID')
1490
                source_node_id = link['source_node']['id']
1491
1492
            target_node_id = None
1493
            if 'id' in link['target_node'].keys():
1494
                if link['target_node']['id'] is not None and \
1495
                        link['target_node']['id'] <= 0:
1496
                    raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
1497
                                           description='API.INVALID_TARGET_NODE_ID')
1498
                target_node_id = link['target_node']['id']
1499
1500
            meter_uuid = None
1501
            if 'uuid' in link['meter'].keys():
1502
                if link['meter']['uuid'] is not None and \
1503
                        isinstance(link['meter']['uuid'], str) and \
1504
                        len(str.strip(link['meter']['uuid'])) > 0:
1505
                    meter_uuid = str.strip(link['meter']['uuid'])
1506
1507
            cursor.execute(" SELECT name "
1508
                           " FROM tbl_energy_flow_diagrams "
1509
                           " WHERE id = %s ", (new_id,))
1510
            if cursor.fetchone() is None:
1511
                cursor.close()
1512
                cnx.close()
1513
                raise falcon.HTTPError(status=falcon.HTTP_400, title='API.NOT_FOUND',
1514
                                       description='API.ENERGY_FLOW_DIAGRAM_NOT_FOUND')
1515
1516
            cursor.execute(" SELECT id "
1517
                           " FROM tbl_energy_flow_diagrams_links "
1518
                           " WHERE energy_flow_diagram_id = %s AND "
1519
                           "       source_node_id = %s AND target_node_id = %s ",
1520
                           (new_id, source_node_id, target_node_id,))
1521
            row = cursor.fetchone()
1522
            if row is not None:
1523
                cursor.close()
1524
                cnx.close()
1525
                raise falcon.HTTPError(status=falcon.HTTP_400,
1526
                                       title='API.NOT_FOUND',
1527
                                       description='API.ENERGY_FLOW_DIAGRAM_LINK_IS_ALREADY_IN_USE')
1528
1529
            query = (" SELECT id, name "
1530
                     " FROM tbl_energy_flow_diagrams_nodes "
1531
                     " WHERE id = %s ")
1532
            cursor.execute(query, (source_node_id,))
1533
            if cursor.fetchone() is None:
1534
                cursor.close()
1535
                cnx.close()
1536
                raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
1537
                                       description='API.SOURCE_NODE_NOT_FOUND')
1538
1539
            query = (" SELECT id, name "
1540
                     " FROM tbl_energy_flow_diagrams_nodes "
1541
                     " WHERE id = %s ")
1542
            cursor.execute(query, (target_node_id,))
1543
            if cursor.fetchone() is None:
1544
                cursor.close()
1545
                cnx.close()
1546
                raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
1547
                                       description='API.TARGET_NODE_NOT_FOUND')
1548
1549
            query = (" SELECT id, name, uuid "
1550
                     " FROM tbl_meters ")
1551
            cursor.execute(query)
1552
            rows_meters = cursor.fetchall()
1553
1554
            meter_dict = dict()
1555
            if rows_meters is not None and len(rows_meters) > 0:
1556
                for row in rows_meters:
1557
                    meter_dict[row[2]] = {"type": 'meter',
1558
                                          "id": row[0],
1559
                                          "name": row[1],
1560
                                          "uuid": row[2]}
1561
1562
            query = (" SELECT id, name, uuid "
1563
                     " FROM tbl_offline_meters ")
1564
            cursor.execute(query)
1565
            rows_offline_meters = cursor.fetchall()
1566
1567
            offline_meter_dict = dict()
1568
            if rows_offline_meters is not None and len(rows_offline_meters) > 0:
1569
                for row in rows_offline_meters:
1570
                    offline_meter_dict[row[2]] = {"type": 'offline_meter',
1571
                                                  "id": row[0],
1572
                                                  "name": row[1],
1573
                                                  "uuid": row[2]}
1574
1575
            query = (" SELECT id, name, uuid "
1576
                     " FROM tbl_virtual_meters ")
1577
            cursor.execute(query)
1578
            rows_virtual_meters = cursor.fetchall()
1579
1580
            virtual_meter_dict = dict()
1581
            if rows_virtual_meters is not None and len(rows_virtual_meters) > 0:
1582
                for row in rows_virtual_meters:
1583
                    virtual_meter_dict[row[2]] = {"type": 'virtual_meter',
1584
                                                  "id": row[0],
1585
                                                  "name": row[1],
1586
                                                  "uuid": row[2]}
1587
1588
            # validate meter uuid
1589
            if meter_dict.get(meter_uuid) is None and \
1590
                    virtual_meter_dict.get(meter_uuid) is None and \
1591
                    offline_meter_dict.get(meter_uuid) is None:
1592
                raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
1593
                                       description='API.INVALID_METER_UUID')
1594
1595
            add_values = (" INSERT INTO tbl_energy_flow_diagrams_links "
1596
                          "    (energy_flow_diagram_id, source_node_id, target_node_id, meter_uuid) "
1597
                          " VALUES (%s, %s, %s, %s) ")
1598
            cursor.execute(add_values, (new_id,
1599
                                        source_node_id,
1600
                                        target_node_id,
1601
                                        meter_uuid))
1602
        cnx.commit()
1603
        cursor.close()
1604
        cnx.close()
1605
1606
        resp.status = falcon.HTTP_201
1607
        resp.location = '/energyflowdiagrams/' + str(new_id)
1608
1609
1610
class EnergyFlowDiagramClone:
1611
    def __init__(self):
1612
        """"Initializes EnergyFlowDiagramClone"""
1613
        pass
1614
1615
    @staticmethod
1616
    def on_options(req, resp, id_):
1617
        _ = req
1618
        resp.status = falcon.HTTP_200
1619
        _ = id_
1620
1621
    @staticmethod
1622
    @user_logger
1623
    def on_post(req, resp, id_):
1624
        admin_control(req)
1625
        if not id_.isdigit() or int(id_) <= 0:
1626
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
1627
                                   description='API.INVALID_ENERGY_FLOW_DIAGRAM_ID')
1628
1629
        cnx = mysql.connector.connect(**config.myems_system_db)
1630
        cursor = cnx.cursor()
1631
1632
        query = (" SELECT id, name, uuid "
1633
                 " FROM tbl_meters ")
1634
        cursor.execute(query)
1635
        rows_meters = cursor.fetchall()
1636
1637
        meter_dict = dict()
1638
        if rows_meters is not None and len(rows_meters) > 0:
1639
            for row in rows_meters:
1640
                meter_dict[row[2]] = {"type": 'meter',
1641
                                      "id": row[0],
1642
                                      "name": row[1],
1643
                                      "uuid": row[2]}
1644
1645
        query = (" SELECT id, name, uuid "
1646
                 " FROM tbl_offline_meters ")
1647
        cursor.execute(query)
1648
        rows_offline_meters = cursor.fetchall()
1649
1650
        offline_meter_dict = dict()
1651
        if rows_offline_meters is not None and len(rows_offline_meters) > 0:
1652
            for row in rows_offline_meters:
1653
                offline_meter_dict[row[2]] = {"type": 'offline_meter',
1654
                                              "id": row[0],
1655
                                              "name": row[1],
1656
                                              "uuid": row[2]}
1657
1658
        query = (" SELECT id, name, uuid "
1659
                 " FROM tbl_virtual_meters ")
1660
        cursor.execute(query)
1661
        rows_virtual_meters = cursor.fetchall()
1662
1663
        virtual_meter_dict = dict()
1664
        if rows_virtual_meters is not None and len(rows_virtual_meters) > 0:
1665
            for row in rows_virtual_meters:
1666
                virtual_meter_dict[row[2]] = {"type": 'virtual_meter',
1667
                                              "id": row[0],
1668
                                              "name": row[1],
1669
                                              "uuid": row[2]}
1670
1671
        query = (" SELECT id, energy_flow_diagram_id, name "
1672
                 " FROM tbl_energy_flow_diagrams_nodes")
1673
        cursor.execute(query)
1674
        rows_nodes = cursor.fetchall()
1675
1676
        node_dict = dict()
1677
        node_list_dict = dict()
1678
        if rows_nodes is not None and len(rows_nodes) > 0:
1679
            for row in rows_nodes:
1680
                node_dict[row[0]] = row[2]
1681
                if node_list_dict.get(row[1]) is None:
1682
                    node_list_dict[row[1]] = list()
1683
                node_list_dict[row[1]].append({"id": row[0], "name": row[2]})
1684
1685
        query = (" SELECT id, energy_flow_diagram_id, source_node_id, target_node_id, meter_uuid "
1686
                 " FROM tbl_energy_flow_diagrams_links")
1687
        cursor.execute(query)
1688
        rows_links = cursor.fetchall()
1689
1690
        link_list_dict = dict()
1691
        if rows_links is not None and len(rows_links) > 0:
1692
            for row in rows_links:
1693
                # find meter by uuid
1694
                meter = meter_dict.get(row[4], None)
1695
                if meter is None:
1696
                    meter = virtual_meter_dict.get(row[4], None)
1697
                if meter is None:
1698
                    meter = offline_meter_dict.get(row[4], None)
1699
1700
                if link_list_dict.get(row[1]) is None:
1701
                    link_list_dict[row[1]] = list()
1702
                link_list_dict[row[1]].append({"id": row[0],
1703
                                               "source_node": {
1704
                                                   "id": row[2],
1705
                                                   "name": node_dict.get(row[2])},
1706
                                               "target_node": {
1707
                                                   "id": row[3],
1708
                                                   "name": node_dict.get(row[3])},
1709
                                               "meter": meter})
1710
1711
        query = (" SELECT id, name, uuid "
1712
                 " FROM tbl_energy_flow_diagrams "
1713
                 " WHERE id = %s ")
1714
        cursor.execute(query, (id_,))
1715
        row = cursor.fetchone()
1716
1717
        if row is None:
1718
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
1719
                                   description='API.ENERGY_FLOW_DIAGRAM_NOT_FOUND')
1720
        else:
1721
            meta_result = {"id": row[0],
1722
                           "name": row[1],
1723
                           "uuid": row[2],
1724
                           "nodes": node_list_dict.get(row[0], None),
1725
                           "links": link_list_dict.get(row[0], None),
1726
                           }
1727
            timezone_offset = int(config.utc_offset[1:3]) * 60 + int(config.utc_offset[4:6])
1728
            if config.utc_offset[0] == '-':
1729
                timezone_offset = -timezone_offset
1730
            new_name = (str.strip(meta_result['name']) +
1731
                        (datetime.utcnow() + timedelta(minutes=timezone_offset)).isoformat(sep='-', timespec='seconds'))
1732
            add_values = (" INSERT INTO tbl_energy_flow_diagrams "
1733
                          "    (name, uuid) "
1734
                          " VALUES (%s, %s) ")
1735
            cursor.execute(add_values, (new_name,
1736
                                        str(uuid.uuid4())))
1737
            new_id = cursor.lastrowid
1738
            if meta_result['nodes'] is not None and len(meta_result['nodes']) > 0:
1739
                for node in meta_result['nodes']:
1740
                    add_values = (" INSERT INTO tbl_energy_flow_diagrams_nodes "
1741
                                  "    (energy_flow_diagram_id, name) "
1742
                                  " VALUES (%s, %s) ")
1743
                    cursor.execute(add_values, (new_id,
1744
                                                node['name']))
1745
            if meta_result['links'] is not None and len(meta_result['links']) > 0:
1746
                for link in meta_result['links']:
1747
                    if link['meter'] is None:
1748
                        continue
1749
                    add_values = (" INSERT INTO tbl_energy_flow_diagrams_links "
1750
                                  "    (energy_flow_diagram_id, source_node_id, target_node_id, meter_uuid) "
1751
                                  " VALUES (%s, %s, %s, %s) ")
1752
                    cursor.execute(add_values, (new_id,
1753
                                                link['source_node']['id'],
1754
                                                link['target_node']['id'],
1755
                                                link['meter']['uuid']))
1756
            cnx.commit()
1757
            cursor.close()
1758
            cnx.close()
1759
1760
            resp.status = falcon.HTTP_201
1761
            resp.location = '/energyflowdiagrams/' + str(new_id)
1762
1763