EnergyFlowDiagramNodeItem.on_options()   A
last analyzed

Complexity

Conditions 1

Size

Total Lines 5
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

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