EnergyFlowDiagramItem.__init__()   A
last analyzed

Complexity

Conditions 1

Size

Total Lines 2
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

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