EquipmentOfflineMeterItem.__init__()   A
last analyzed

Complexity

Conditions 1

Size

Total Lines 2
Code Lines 2

Duplication

Lines 2
Ratio 100 %

Importance

Changes 0
Metric Value
eloc 2
dl 2
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
import redis
7
from core.useractivity import user_logger, admin_control, access_control, api_key_control
8
import config
9
from decimal import Decimal
10
11
12
def clear_equipment_cache(equipment_id=None):
13
    """
14
    Clear equipment-related cache after data modification
15
16
    Args:
17
        equipment_id: Equipment ID (optional, for specific equipment cache)
18
    """
19
    # Check if Redis is enabled
20
    if not config.redis.get('is_enabled', False):
21
        return
22
23
    redis_client = None
24
    try:
25
        redis_client = redis.Redis(
26
            host=config.redis['host'],
27
            port=config.redis['port'],
28
            password=config.redis['password'] if config.redis['password'] else None,
29
            db=config.redis['db'],
30
            decode_responses=True,
31
            socket_connect_timeout=2,
32
            socket_timeout=2
33
        )
34
        redis_client.ping()
35
36
        # Clear equipment list cache
37
        list_cache_key_pattern = 'equipment:list*'
38
        matching_keys = redis_client.keys(list_cache_key_pattern)
39
        if matching_keys:
40
            redis_client.delete(*matching_keys)
41
42
        # Clear specific equipment cache if equipment_id is provided
43
        if equipment_id:
44
            item_cache_key = f'equipment:item:{equipment_id}'
45
            redis_client.delete(item_cache_key)
46
47
            # Clear related caches
48
            related_cache_patterns = [
49
                f'equipment:parameters:{equipment_id}*',
50
                f'equipment:meters:{equipment_id}*',
51
                f'equipment:offlinemeters:{equipment_id}*',
52
                f'equipment:virtualmeters:{equipment_id}*',
53
                f'equipment:commands:{equipment_id}*',
54
                f'equipment:export:{equipment_id}*',
55
                f'equipment:datasources:{equipment_id}*',
56
                f'equipment:addpoints:{equipment_id}*',
57
                f'equipment:editpoints:{equipment_id}:*'
58
            ]
59
            for pattern in related_cache_patterns:
60
                matching_keys = redis_client.keys(pattern)
61
                if matching_keys:
62
                    redis_client.delete(*matching_keys)
63
64
    except Exception:
65
        # If cache clear fails, ignore and continue
66
        pass
67
68
69
class EquipmentCollection:
70
    """
71
    Equipment Collection Resource
72
73
    This class handles CRUD operations for equipment collection.
74
    It provides endpoints for listing all equipment and creating new equipment.
75
    Equipment represents physical devices and systems in the energy management system.
76
    """
77
    def __init__(self):
78
        """Initialize EquipmentCollection"""
79
        pass
80
81
    @staticmethod
82
    def on_options(req, resp):
83
        """Handle OPTIONS requests for CORS preflight"""
84
        _ = req
85
        resp.status = falcon.HTTP_200
86
87
    @staticmethod
88
    def on_get(req, resp):
89
        if 'API-KEY' not in req.headers or \
90
                not isinstance(req.headers['API-KEY'], str) or \
91
                len(str.strip(req.headers['API-KEY'])) == 0:
92
            access_control(req)
93
        else:
94
            api_key_control(req)
95
96
        # Build cache key with search query if present
97
        search_query = req.get_param('q')
98
        if search_query and isinstance(search_query, str) and len(str.strip(search_query)) > 0:
99
            cache_key = f'equipment:list:q:{str.strip(search_query)}'
100
        else:
101
            cache_key = 'equipment:list'
102
        cache_expire = 28800  # 8 hours in seconds (long-term cache)
103
104
        # Try to get from Redis cache (only if Redis is enabled)
105
        redis_client = None
106
        if config.redis.get('is_enabled', False):
107
            try:
108
                redis_client = redis.Redis(
109
                    host=config.redis['host'],
110
                    port=config.redis['port'],
111
                    password=config.redis['password'] if config.redis['password'] else None,
112
                    db=config.redis['db'],
113
                    decode_responses=True,
114
                    socket_connect_timeout=2,
115
                    socket_timeout=2
116
                )
117
                redis_client.ping()
118
                cached_result = redis_client.get(cache_key)
119
                if cached_result:
120
                    resp.text = cached_result
121
                    return
122
            except Exception:
123
                # If Redis connection fails, continue to database query
124
                pass
125
126
        cnx = mysql.connector.connect(**config.myems_system_db)
127
        cursor = cnx.cursor()
128
129
        query = (" SELECT id, name, uuid "
130
                 " FROM tbl_cost_centers ")
131
        cursor.execute(query)
132
        rows_cost_centers = cursor.fetchall()
133
134
        cost_center_dict = dict()
135
        if rows_cost_centers is not None and len(rows_cost_centers) > 0:
136
            for row in rows_cost_centers:
137
                cost_center_dict[row[0]] = {"id": row[0],
138
                                            "name": row[1],
139
                                            "uuid": row[2]}
140
141
        query_svg = (" SELECT id, name, uuid "
142
                     " FROM tbl_svgs ")
143
        cursor.execute(query_svg)
144
        rows_svgs = cursor.fetchall()
145
146
        svg_dict = dict()
147
        if rows_svgs is not None and len(rows_svgs) > 0:
148
            for row in rows_svgs:
149
                svg_dict[row[0]] = {"id": row[0],
150
                                    "name": row[1],
151
                                    "uuid": row[2]}
152
153
        search_query = req.get_param('q')
154
        query_base = (" SELECT id, name, uuid, "
155
                      "        is_input_counted, is_output_counted, "
156
                      "        cost_center_id, svg_id, camera_url, description "
157
                      " FROM tbl_equipments ")
158
        params = []
159
160
        if search_query and isinstance(search_query, str) and len(str.strip(search_query)) > 0:
161
            query_base += " WHERE name LIKE %s OR description LIKE %s "
162
            trimmed_query = str.strip(search_query)
163
            params = [f'%{trimmed_query}%', f'%{trimmed_query}%']
164
165
        query_base += " ORDER BY id "
166
        cursor.execute(query_base, params)
167
        rows_equipments = cursor.fetchall()
168
169
        result = list()
170
        if rows_equipments is not None and len(rows_equipments) > 0:
171
            for row in rows_equipments:
172
                meta_result = {"id": row[0],
173
                               "name": row[1],
174
                               "uuid": row[2],
175
                               "is_input_counted": bool(row[3]),
176
                               "is_output_counted": bool(row[4]),
177
                               "cost_center": cost_center_dict.get(row[5], None),
178
                               "svg": svg_dict.get(row[6], None),
179
                               "camera_url": row[7],
180
                               "description": row[8],
181
                               "qrcode": 'equipment:' + row[2]}
182
                result.append(meta_result)
183
184
        cursor.close()
185
        cnx.close()
186
187
        # Store result in Redis cache
188
        result_json = json.dumps(result)
189
        if redis_client:
190
            try:
191
                redis_client.setex(cache_key, cache_expire, result_json)
192
            except Exception:
193
                # If cache set fails, ignore and continue
194
                pass
195
196
        resp.text = result_json
197
198 View Code Duplication
    @staticmethod
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
199
    @user_logger
200
    def on_post(req, resp):
201
        """Handles POST requests"""
202
        admin_control(req)
203
        try:
204
            raw_json = req.stream.read().decode('utf-8')
205
        except UnicodeDecodeError as ex:
206
            print("Failed to decode request")
207
            raise falcon.HTTPError(status=falcon.HTTP_400,
208
                                   title='API.BAD_REQUEST',
209
                                   description='API.INVALID_ENCODING')
210
        except Exception as ex:
211
            print("Unexpected error reading request stream")
212
            raise falcon.HTTPError(status=falcon.HTTP_400,
213
                                   title='API.BAD_REQUEST',
214
                                   description='API.FAILED_TO_READ_REQUEST_STREAM')
215
216
        new_values = json.loads(raw_json)
217
218
        if 'name' not in new_values['data'].keys() or \
219
                not isinstance(new_values['data']['name'], str) or \
220
                len(str.strip(new_values['data']['name'])) == 0:
221
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
222
                                   description='API.INVALID_EQUIPMENT_NAME')
223
        name = str.strip(new_values['data']['name'])
224
225
        if 'is_input_counted' not in new_values['data'].keys() or \
226
                not isinstance(new_values['data']['is_input_counted'], bool):
227
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
228
                                   description='API.INVALID_IS_INPUT_COUNTED_VALUE')
229
        is_input_counted = new_values['data']['is_input_counted']
230
231
        if 'is_output_counted' not in new_values['data'].keys() or \
232
                not isinstance(new_values['data']['is_output_counted'], bool):
233
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
234
                                   description='API.INVALID_IS_OUTPUT_COUNTED_VALUE')
235
        is_output_counted = new_values['data']['is_output_counted']
236
237
        if 'cost_center_id' not in new_values['data'].keys() or \
238
                not isinstance(new_values['data']['cost_center_id'], int) or \
239
                new_values['data']['cost_center_id'] <= 0:
240
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
241
                                   description='API.INVALID_COST_CENTER_ID')
242
        cost_center_id = new_values['data']['cost_center_id']
243
244
        if 'svg_id' in new_values['data'].keys() and \
245
                isinstance(new_values['data']['svg_id'], int) and \
246
                new_values['data']['svg_id'] > 0:
247
            svg_id = new_values['data']['svg_id']
248
        else:
249
            svg_id = None
250
251
        if 'camera_url' in new_values['data'].keys() and \
252
                new_values['data']['camera_url'] is not None and \
253
                len(str(new_values['data']['camera_url'])) > 0:
254
            camera_url = str.strip(new_values['data']['camera_url'])
255
        else:
256
            camera_url = None
257
258
        if 'description' in new_values['data'].keys() and \
259
                new_values['data']['description'] is not None and \
260
                len(str(new_values['data']['description'])) > 0:
261
            description = str.strip(new_values['data']['description'])
262
        else:
263
            description = None
264
265
        cnx = mysql.connector.connect(**config.myems_system_db)
266
        cursor = cnx.cursor()
267
268
        cursor.execute(" SELECT name "
269
                       " FROM tbl_equipments "
270
                       " WHERE name = %s ", (name,))
271
        if cursor.fetchone() is not None:
272
            cursor.close()
273
            cnx.close()
274
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
275
                                   description='API.EQUIPMENT_NAME_IS_ALREADY_IN_USE')
276
277
        if cost_center_id is not None:
278
            cursor.execute(" SELECT name "
279
                           " FROM tbl_cost_centers "
280
                           " WHERE id = %s ",
281
                           (new_values['data']['cost_center_id'],))
282
            row = cursor.fetchone()
283
            if row is None:
284
                cursor.close()
285
                cnx.close()
286
                raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
287
                                       description='API.COST_CENTER_NOT_FOUND')
288
289
        if svg_id is not None:
290
            cursor.execute(" SELECT name "
291
                           " FROM tbl_svgs "
292
                           " WHERE id = %s ",
293
                           (svg_id,))
294
            row = cursor.fetchone()
295
            if row is None:
296
                cursor.close()
297
                cnx.close()
298
                raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
299
                                       description='API.SVG_NOT_FOUND')
300
301
        add_values = (" INSERT INTO tbl_equipments "
302
                      "    (name, uuid, is_input_counted, is_output_counted, "
303
                      "     cost_center_id, svg_id, camera_url, description) "
304
                      " VALUES (%s, %s, %s, %s, %s, %s, %s, %s) ")
305
        cursor.execute(add_values, (name,
306
                                    str(uuid.uuid4()),
307
                                    is_input_counted,
308
                                    is_output_counted,
309
                                    cost_center_id,
310
                                    svg_id,
311
                                    camera_url,
312
                                    description))
313
        new_id = cursor.lastrowid
314
        cnx.commit()
315
        cursor.close()
316
        cnx.close()
317
318
        # Clear cache after creating new equipment
319
        clear_equipment_cache()
320
321
        resp.status = falcon.HTTP_201
322
        resp.location = '/equipments/' + str(new_id)
323
324
325
class EquipmentItem:
326
    def __init__(self):
327
        pass
328
329
    @staticmethod
330
    def on_options(req, resp, id_):
331
        _ = req
332
        resp.status = falcon.HTTP_200
333
        _ = id_
334
335 View Code Duplication
    @staticmethod
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
336
    def on_get(req, resp, id_):
337
        if 'API-KEY' not in req.headers or \
338
                not isinstance(req.headers['API-KEY'], str) or \
339
                len(str.strip(req.headers['API-KEY'])) == 0:
340
            access_control(req)
341
        else:
342
            api_key_control(req)
343
        if not id_.isdigit() or int(id_) <= 0:
344
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
345
                                   description='API.INVALID_EQUIPMENT_ID')
346
347
        # Redis cache key
348
        cache_key = f'equipment:item:{id_}'
349
        cache_expire = 28800  # 8 hours in seconds (long-term cache)
350
351
        # Try to get from Redis cache (only if Redis is enabled)
352
        redis_client = None
353
        if config.redis.get('is_enabled', False):
354
            try:
355
                redis_client = redis.Redis(
356
                    host=config.redis['host'],
357
                    port=config.redis['port'],
358
                    password=config.redis['password'] if config.redis['password'] else None,
359
                    db=config.redis['db'],
360
                    decode_responses=True,
361
                    socket_connect_timeout=2,
362
                    socket_timeout=2
363
                )
364
                redis_client.ping()
365
                cached_result = redis_client.get(cache_key)
366
                if cached_result:
367
                    resp.text = cached_result
368
                    return
369
            except Exception:
370
                # If Redis connection fails, continue to database query
371
                pass
372
373
        cnx = mysql.connector.connect(**config.myems_system_db)
374
        cursor = cnx.cursor()
375
376
        query = (" SELECT id, name, uuid "
377
                 " FROM tbl_cost_centers ")
378
        cursor.execute(query)
379
        rows_cost_centers = cursor.fetchall()
380
381
        cost_center_dict = dict()
382
        if rows_cost_centers is not None and len(rows_cost_centers) > 0:
383
            for row in rows_cost_centers:
384
                cost_center_dict[row[0]] = {"id": row[0],
385
                                            "name": row[1],
386
                                            "uuid": row[2]}
387
388
        svg_dict = dict()
389
        query = (" SELECT id, name, uuid "
390
                 " FROM tbl_svgs ")
391
        cursor.execute(query)
392
        rows_svgs = cursor.fetchall()
393
        if rows_svgs is not None and len(rows_svgs) > 0:
394
            for row in rows_svgs:
395
                svg_dict[row[0]] = {"id": row[0],
396
                                    "name": row[1],
397
                                    "uuid": row[2]}
398
399
        query = (" SELECT id, name, uuid, "
400
                 "        is_input_counted, is_output_counted, "
401
                 "        cost_center_id, svg_id, camera_url, description "
402
                 " FROM tbl_equipments "
403
                 " WHERE id = %s ")
404
        cursor.execute(query, (id_,))
405
        row = cursor.fetchone()
406
        cursor.close()
407
        cnx.close()
408
409
        if row is None:
410
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
411
                                   description='API.EQUIPMENT_NOT_FOUND')
412
        else:
413
            meta_result = {"id": row[0],
414
                           "name": row[1],
415
                           "uuid": row[2],
416
                           "is_input_counted": bool(row[3]),
417
                           "is_output_counted": bool(row[4]),
418
                           "cost_center": cost_center_dict.get(row[5], None),
419
                           "svg": svg_dict.get(row[6], None),
420
                           "camera_url": row[7],
421
                           "description": row[8],
422
                           "qrcode": 'equipment:' + row[2]}
423
424
        # Store result in Redis cache
425
        result_json = json.dumps(meta_result)
426
        if redis_client:
427
            try:
428
                redis_client.setex(cache_key, cache_expire, result_json)
429
            except Exception:
430
                # If cache set fails, ignore and continue
431
                pass
432
433
        resp.text = result_json
434
435
    @staticmethod
436
    @user_logger
437
    @user_logger
438
    def on_delete(req, resp, id_):
439
        admin_control(req)
440
        if not id_.isdigit() or int(id_) <= 0:
441
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
442
                                   description='API.INVALID_EQUIPMENT_ID')
443
444
        cnx = mysql.connector.connect(**config.myems_system_db)
445
        cursor = cnx.cursor()
446
447
        # check relation with space
448
        cursor.execute(" SELECT space_id "
449
                       " FROM tbl_spaces_equipments "
450
                       " WHERE equipment_id = %s ",
451
                       (id_,))
452
        rows_equipments = cursor.fetchall()
453
        if rows_equipments is not None and len(rows_equipments) > 0:
454
            cursor.close()
455
            cnx.close()
456
            raise falcon.HTTPError(status=falcon.HTTP_400,
457
                                   title='API.BAD_REQUEST',
458
                                   description='API.THERE_IS_RELATION_WITH_SPACES')
459
460
        # check relation with combined equipments
461
        cursor.execute(" SELECT combined_equipment_id "
462
                       " FROM tbl_combined_equipments_equipments "
463
                       " WHERE equipment_id = %s ",
464
                       (id_,))
465
        rows_combined_equipments = cursor.fetchall()
466
        if rows_combined_equipments is not None and len(rows_combined_equipments) > 0:
467
            cursor.close()
468
            cnx.close()
469
            raise falcon.HTTPError(status=falcon.HTTP_400,
470
                                   title='API.BAD_REQUEST',
471
                                   description='API.THERE_IS_RELATION_WITH_COMBINED_EQUIPMENTS')
472
473
        # check relation with shopfloor
474
        cursor.execute(" SELECT shopfloor_id "
475
                       " FROM tbl_shopfloors_equipments "
476
                       " WHERE equipment_id = %s ",
477
                       (id_,))
478
        rows_combined_shopfloor = cursor.fetchall()
479
        if rows_combined_shopfloor is not None and len(rows_combined_shopfloor) > 0:
480
            cursor.close()
481
            cnx.close()
482
            raise falcon.HTTPError(status=falcon.HTTP_400,
483
                                   title='API.BAD_REQUEST',
484
                                   description='API.THERE_IS_RELATION_WITH_SHOPFLOORS')
485
486
        # delete relation with meter
487
        cursor.execute(" DELETE FROM tbl_equipments_meters WHERE equipment_id = %s ", (id_,))
488
489
        # delete relation with offline meter
490
        cursor.execute(" DELETE FROM tbl_equipments_offline_meters WHERE equipment_id = %s ", (id_,))
491
492
        # delete relation with virtual meter
493
        cursor.execute(" DELETE FROM tbl_equipments_virtual_meters WHERE equipment_id = %s ", (id_,))
494
495
        # delete relation with commands
496
        cursor.execute(" DELETE FROM tbl_equipments_commands WHERE equipment_id = %s ", (id_,))
497
498
        # delete all associated parameters
499
        cursor.execute(" DELETE FROM tbl_equipments_parameters WHERE equipment_id = %s ", (id_,))
500
        cnx.commit()
501
502
        cursor.execute(" DELETE FROM tbl_equipments WHERE id = %s ", (id_,))
503
        cnx.commit()
504
505
        cursor.close()
506
        cnx.close()
507
508
        # Clear cache after deleting equipment
509
        clear_equipment_cache(equipment_id=id_)
510
511
        resp.status = falcon.HTTP_204
512
513 View Code Duplication
    @staticmethod
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
514
    @user_logger
515
    def on_put(req, resp, id_):
516
        """Handles PUT requests"""
517
        admin_control(req)
518
        if not id_.isdigit() or int(id_) <= 0:
519
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
520
                                   description='API.INVALID_EQUIPMENT_ID')
521
        try:
522
            raw_json = req.stream.read().decode('utf-8')
523
        except UnicodeDecodeError as ex:
524
            print("Failed to decode request")
525
            raise falcon.HTTPError(status=falcon.HTTP_400,
526
                                   title='API.BAD_REQUEST',
527
                                   description='API.INVALID_ENCODING')
528
        except Exception as ex:
529
            print("Unexpected error reading request stream")
530
            raise falcon.HTTPError(status=falcon.HTTP_400,
531
                                   title='API.BAD_REQUEST',
532
                                   description='API.FAILED_TO_READ_REQUEST_STREAM')
533
534
        new_values = json.loads(raw_json)
535
536
        if 'name' not in new_values['data'].keys() or \
537
                not isinstance(new_values['data']['name'], str) or \
538
                len(str.strip(new_values['data']['name'])) == 0:
539
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
540
                                   description='API.INVALID_EQUIPMENT_NAME')
541
        name = str.strip(new_values['data']['name'])
542
543
        if 'is_input_counted' not in new_values['data'].keys() or \
544
                not isinstance(new_values['data']['is_input_counted'], bool):
545
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
546
                                   description='API.INVALID_IS_INPUT_COUNTED_VALUE')
547
        is_input_counted = new_values['data']['is_input_counted']
548
549
        if 'is_output_counted' not in new_values['data'].keys() or \
550
                not isinstance(new_values['data']['is_output_counted'], bool):
551
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
552
                                   description='API.INVALID_IS_OUTPUT_COUNTED_VALUE')
553
        is_output_counted = new_values['data']['is_output_counted']
554
555
        if 'cost_center_id' not in new_values['data'].keys() or \
556
                not isinstance(new_values['data']['cost_center_id'], int) or \
557
                new_values['data']['cost_center_id'] <= 0:
558
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
559
                                   description='API.INVALID_COST_CENTER_ID')
560
        cost_center_id = new_values['data']['cost_center_id']
561
562
        if 'svg_id' in new_values['data'].keys() and \
563
                isinstance(new_values['data']['svg_id'], int) and \
564
                new_values['data']['svg_id'] > 0:
565
            svg_id = new_values['data']['svg_id']
566
        else:
567
            svg_id = None
568
569
        if 'description' in new_values['data'].keys() and \
570
                new_values['data']['description'] is not None and \
571
                len(str(new_values['data']['description'])) > 0:
572
            description = str.strip(new_values['data']['description'])
573
        else:
574
            description = None
575
576
        if 'camera_url' in new_values['data'].keys() and \
577
                new_values['data']['camera_url'] is not None and \
578
                len(str(new_values['data']['camera_url'])) > 0:
579
            camera_url = str.strip(new_values['data']['camera_url'])
580
        else:
581
            camera_url = None
582
583
        cnx = mysql.connector.connect(**config.myems_system_db)
584
        cursor = cnx.cursor()
585
586
        cursor.execute(" SELECT name "
587
                       " FROM tbl_equipments "
588
                       " WHERE id = %s ", (id_,))
589
        if cursor.fetchone() is None:
590
            cursor.close()
591
            cnx.close()
592
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
593
                                   description='API.EQUIPMENT_NOT_FOUND')
594
595
        cursor.execute(" SELECT name "
596
                       " FROM tbl_equipments "
597
                       " WHERE name = %s AND id != %s ", (name, id_))
598
        if cursor.fetchone() is not None:
599
            cursor.close()
600
            cnx.close()
601
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
602
                                   description='API.EQUIPMENT_NAME_IS_ALREADY_IN_USE')
603
604
        cursor.execute(" SELECT name "
605
                       " FROM tbl_cost_centers "
606
                       " WHERE id = %s ",
607
                       (new_values['data']['cost_center_id'],))
608
        row = cursor.fetchone()
609
        if row is None:
610
            cursor.close()
611
            cnx.close()
612
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
613
                                   description='API.COST_CENTER_NOT_FOUND')
614
615
        if svg_id is not None:
616
            cursor.execute(" SELECT name "
617
                           " FROM tbl_svgs "
618
                           " WHERE id = %s ",
619
                           (new_values['data']['svg_id'],))
620
            row = cursor.fetchone()
621
            if row is None:
622
                cursor.close()
623
                cnx.close()
624
                raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
625
                                       description='API.SVG_NOT_FOUND')
626
627
        update_row = (" UPDATE tbl_equipments "
628
                      " SET name = %s, is_input_counted = %s, is_output_counted = %s, "
629
                      "     cost_center_id = %s, svg_id = %s, camera_url = %s, description = %s "
630
                      " WHERE id = %s ")
631
        cursor.execute(update_row, (name,
632
                                    is_input_counted,
633
                                    is_output_counted,
634
                                    cost_center_id,
635
                                    svg_id,
636
                                    camera_url,
637
                                    description,
638
                                    id_))
639
        cnx.commit()
640
641
        cursor.close()
642
        cnx.close()
643
644
        # Clear cache after updating equipment
645
        clear_equipment_cache(equipment_id=id_)
646
647
        resp.status = falcon.HTTP_200
648
649
    # Clone an Equipment
650 View Code Duplication
    @staticmethod
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
651
    @user_logger
652
    def on_post(req, resp, id_):
653
        admin_control(req)
654
        """Handles POST requests"""
655
        if not id_.isdigit() or int(id_) <= 0:
656
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
657
                                   description='API.INVALID_EQUIPMENT_ID')
658
659
        cnx = mysql.connector.connect(**config.myems_system_db)
660
        cursor = cnx.cursor()
661
        cursor.execute(" SELECT name "
662
                       " FROM tbl_equipments "
663
                       " WHERE id = %s ", (id_,))
664
        if cursor.fetchone() is None:
665
            cursor.close()
666
            cnx.close()
667
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
668
                                   description='API.EQUIPMENT_NOT_FOUND')
669
670
        query = (" SELECT name, is_input_counted, is_output_counted, "
671
                 "        cost_center_id, svg_id, camera_url, description "
672
                 " FROM tbl_equipments "
673
                 " WHERE id = %s ")
674
        cursor.execute(query, (id_,))
675
        row = cursor.fetchone()
676
677
        if row is None:
678
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
679
                                   description='API.EQUIPMENT_NOT_FOUND')
680
        else:
681
            add_values = (" INSERT INTO tbl_equipments "
682
                          "    (name, uuid, is_input_counted, is_output_counted, "
683
                          "     cost_center_id, svg_id, camera_url, description) "
684
                          " VALUES (%s, %s, %s, %s, %s, %s, %s, %s) ")
685
            cursor.execute(add_values, (row[0] + ' Copy',
686
                                        str(uuid.uuid4()),
687
                                        row[1],
688
                                        row[2],
689
                                        row[3],
690
                                        row[4],
691
                                        row[5],
692
                                        row[6]))
693
            new_id = cursor.lastrowid
694
            cnx.commit()
695
696
        # clone relation with meter
697
        cursor.execute(" SELECT meter_id, is_output "
698
                       " FROM tbl_equipments_meters "
699
                       " WHERE equipment_id = %s ",
700
                       (id_,))
701
        rows_meters = cursor.fetchall()
702
        if rows_meters is not None and len(rows_meters) > 0:
703
            add_values = (" INSERT INTO tbl_equipments_meters (equipment_id, meter_id, is_output) "
704
                          " VALUES  ")
705
            for row in rows_meters:
706
                add_values += " (" + str(new_id) + ","
707
                add_values += str(row[0]) + ","
708
                add_values += str(bool(row[1])) + "), "
709
            # trim ", " at the end of string and then execute
710
            cursor.execute(add_values[:-2])
711
            cnx.commit()
712
713
        # clone relation with offline meter
714
        cursor.execute(" SELECT offline_meter_id, is_output "
715
                       " FROM tbl_equipments_offline_meters "
716
                       " WHERE equipment_id = %s ",
717
                       (id_,))
718
        rows_offline_meters = cursor.fetchall()
719
        if rows_offline_meters is not None and len(rows_offline_meters) > 0:
720
            add_values = (" INSERT INTO tbl_equipments_offline_meters (equipment_id, offline_meter_id, is_output) "
721
                          " VALUES  ")
722
            for row in rows_offline_meters:
723
                add_values += " (" + str(new_id) + ","
724
                add_values += "'" + str(row[0]) + "',"
725
                add_values += str(bool(row[1])) + "), "
726
            # trim ", " at the end of string and then execute
727
            cursor.execute(add_values[:-2])
728
            cnx.commit()
729
730
        # clone relation with virtual meter
731
        cursor.execute(" SELECT virtual_meter_id, is_output "
732
                       " FROM tbl_equipments_virtual_meters "
733
                       " WHERE equipment_id = %s ",
734
                       (id_,))
735
        rows_virtual_meters = cursor.fetchall()
736
        if rows_virtual_meters is not None and len(rows_virtual_meters) > 0:
737
            add_values = (" INSERT INTO tbl_equipments_virtual_meters (equipment_id, virtual_meter_id, is_output) "
738
                          " VALUES  ")
739
            for row in rows_virtual_meters:
740
                add_values += " (" + str(new_id) + ","
741
                add_values += str(row[0]) + ","
742
                add_values += str(bool(row[1])) + "), "
743
            # trim ", " at the end of string and then execute
744
            cursor.execute(add_values[:-2])
745
            cnx.commit()
746
747
        # clone parameters
748
        cursor.execute(" SELECT name, parameter_type, constant, point_id, numerator_meter_uuid, denominator_meter_uuid "
749
                       " FROM tbl_equipments_parameters "
750
                       " WHERE equipment_id = %s ",
751
                       (id_,))
752
        rows_parameters = cursor.fetchall()
753
        if rows_parameters is not None and len(rows_parameters) > 0:
754
            add_values = (" INSERT INTO tbl_equipments_parameters"
755
                          "     (equipment_id, name, parameter_type, constant, point_id, "
756
                          "      numerator_meter_uuid, denominator_meter_uuid) "
757
                          " VALUES  ")
758
            for row in rows_parameters:
759
                add_values += " (" + str(new_id) + ","
760
                add_values += "'" + str(row[0]) + "',"
761
                add_values += "'" + str(row[1]) + "',"
762
                if row[2] is not None:
763
                    add_values += "'" + str(row[2]) + "',"
764
                else:
765
                    add_values += "null, "
766
767
                if row[3] is not None:
768
                    add_values += str(row[3]) + ","
769
                else:
770
                    add_values += "null, "
771
772
                if row[4] is not None:
773
                    add_values += "'" + row[4] + "',"
774
                else:
775
                    add_values += "null, "
776
                if row[5] is not None:
777
                    add_values += "'" + row[5] + "'), "
778
                else:
779
                    add_values += "null), "
780
781
            # trim ", " at the end of string and then execute
782
            cursor.execute(add_values[:-2])
783
            cnx.commit()
784
785
        cursor.close()
786
        cnx.close()
787
788
        # Clear cache after cloning equipment
789
        clear_equipment_cache()
790
791
        resp.status = falcon.HTTP_201
792
        resp.location = '/equipments/' + str(new_id)
793
794
795
class EquipmentParameterCollection:
796
    def __init__(self):
797
        pass
798
799
    @staticmethod
800
    def on_options(req, resp, id_):
801
        _ = req
802
        resp.status = falcon.HTTP_200
803
        _ = id_
804
805
    @staticmethod
806
    def on_get(req, resp, id_):
807
        if 'API-KEY' not in req.headers or \
808
                not isinstance(req.headers['API-KEY'], str) or \
809
                len(str.strip(req.headers['API-KEY'])) == 0:
810
            access_control(req)
811
        else:
812
            api_key_control(req)
813
        if not id_.isdigit() or int(id_) <= 0:
814
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
815
                                   description='API.INVALID_EQUIPMENT_ID')
816
817
        # Redis cache key
818
        cache_key = f'equipment:parameters:{id_}'
819
        cache_expire = 28800  # 8 hours in seconds (long-term cache)
820
821
        # Try to get from Redis cache (only if Redis is enabled)
822
        redis_client = None
823
        if config.redis.get('is_enabled', False):
824
            try:
825
                redis_client = redis.Redis(
826
                    host=config.redis['host'],
827
                    port=config.redis['port'],
828
                    password=config.redis['password'] if config.redis['password'] else None,
829
                    db=config.redis['db'],
830
                    decode_responses=True,
831
                    socket_connect_timeout=2,
832
                    socket_timeout=2
833
                )
834
                redis_client.ping()
835
                cached_result = redis_client.get(cache_key)
836
                if cached_result:
837
                    resp.text = cached_result
838
                    return
839
            except Exception:
840
                # If Redis connection fails, continue to database query
841
                pass
842
843
        cnx = mysql.connector.connect(**config.myems_system_db)
844
        cursor = cnx.cursor()
845
846
        cursor.execute(" SELECT id "
847
                       " FROM tbl_equipments_data_sources "
848
                       " WHERE equipment_id = %s ", (id_,))
849
        rows = cursor.fetchall()
850
        if rows is not None and len(rows) > 0:
851
            is_bind_data_source = True
852
        else:
853
            is_bind_data_source = False
854
855
        cursor.execute(" SELECT name "
856
                       " FROM tbl_equipments "
857
                       " WHERE id = %s ", (id_,))
858
        if cursor.fetchone() is None:
859
            cursor.close()
860
            cnx.close()
861
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
862
                                   description='API.EQUIPMENT_NOT_FOUND')
863
864
        query = (" SELECT id, name "
865
                 " FROM tbl_points ")
866
        cursor.execute(query)
867
        rows_points = cursor.fetchall()
868
869
        point_dict = dict()
870
        if rows_points is not None and len(rows_points) > 0:
871
            for row in rows_points:
872
                point_dict[row[0]] = {"id": row[0],
873
                                      "name": row[1]}
874
875
        query = (" SELECT id, name, uuid "
876
                 " FROM tbl_meters ")
877
        cursor.execute(query)
878
        rows_meters = cursor.fetchall()
879
880
        meter_dict = dict()
881
        if rows_meters is not None and len(rows_meters) > 0:
882
            for row in rows_meters:
883
                meter_dict[row[2]] = {"type": 'meter',
884
                                      "id": row[0],
885
                                      "name": row[1],
886
                                      "uuid": row[2]}
887
888
        query = (" SELECT id, name, uuid "
889
                 " FROM tbl_offline_meters ")
890
        cursor.execute(query)
891
        rows_offline_meters = cursor.fetchall()
892
893
        offline_meter_dict = dict()
894
        if rows_offline_meters is not None and len(rows_offline_meters) > 0:
895
            for row in rows_offline_meters:
896
                offline_meter_dict[row[2]] = {"type": 'offline_meter',
897
                                              "id": row[0],
898
                                              "name": row[1],
899
                                              "uuid": row[2]}
900
901
        query = (" SELECT id, name, uuid "
902
                 " FROM tbl_virtual_meters ")
903
        cursor.execute(query)
904
        rows_virtual_meters = cursor.fetchall()
905
906
        virtual_meter_dict = dict()
907
        if rows_virtual_meters is not None and len(rows_virtual_meters) > 0:
908
            for row in rows_virtual_meters:
909
                virtual_meter_dict[row[2]] = {"type": 'virtual_meter',
910
                                              "id": row[0],
911
                                              "name": row[1],
912
                                              "uuid": row[2]}
913
914
        query = (" SELECT id, name, parameter_type, "
915
                 "        constant, point_id, numerator_meter_uuid, denominator_meter_uuid "
916
                 " FROM tbl_equipments_parameters "
917
                 " WHERE equipment_id = %s "
918
                 " ORDER BY id ")
919
        cursor.execute(query, (id_, ))
920
        rows_parameters = cursor.fetchall()
921
922
        last_index = 0
923
        is_finish_get_data = False
924
        result = list()
925 View Code Duplication
        if rows_parameters is not None and len(rows_parameters) > 0:
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
926
            for row in rows_parameters:
927
                constant = None
928
                point = None
929
                numerator_meter = None
930
                denominator_meter = None
931
                if row[2] == 'point':
932
                    point = point_dict.get(row[4], None)
933
                    constant = None
934
                    numerator_meter = None
935
                    denominator_meter = None
936
                elif row[2] == 'constant':
937
                    constant = row[3]
938
                    point = None
939
                    numerator_meter = None
940
                    denominator_meter = None
941
                elif row[2] == 'fraction':
942
                    constant = None
943
                    point = None
944
                    # find numerator meter by uuid
945
                    numerator_meter = meter_dict.get(row[5], None)
946
                    if numerator_meter is None:
947
                        numerator_meter = virtual_meter_dict.get(row[5], None)
948
                    if numerator_meter is None:
949
                        numerator_meter = offline_meter_dict.get(row[5], None)
950
                    # find denominator meter by uuid
951
                    denominator_meter = meter_dict.get(row[6], None)
952
                    if denominator_meter is None:
953
                        denominator_meter = virtual_meter_dict.get(row[6], None)
954
                    if denominator_meter is None:
955
                        denominator_meter = offline_meter_dict.get(row[6], None)
956
957
                meta_result = {"id": row[0],
958
                               "name": row[1],
959
                               "parameter_type": row[2],
960
                               "constant": constant,
961
                               "point": point,
962
                               "numerator_meter": numerator_meter,
963
                               "denominator_meter": denominator_meter}
964
                result.append(meta_result)
965
                last_index = meta_result['id']
966
967
        cursor.close()
968
        cnx.close()
969
970
        # Store result in Redis cache
971
        result_json = json.dumps(result)
972
        if redis_client:
973
            try:
974
                redis_client.setex(cache_key, cache_expire, result_json)
975
            except Exception:
976
                # If cache set fails, ignore and continue
977
                pass
978
979
        resp.text = result_json
980
981
    @staticmethod
982
    @user_logger
983
    def on_post(req, resp, id_):
984
        """Handles POST requests"""
985
        admin_control(req)
986
        if not id_.isdigit() or int(id_) <= 0:
987
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
988
                                   description='API.INVALID_EQUIPMENT_ID')
989
        try:
990
            raw_json = req.stream.read().decode('utf-8')
991
        except UnicodeDecodeError as ex:
992
            print("Failed to decode request")
993
            raise falcon.HTTPError(status=falcon.HTTP_400,
994
                                   title='API.BAD_REQUEST',
995
                                   description='API.INVALID_ENCODING')
996
        except Exception as ex:
997
            print("Unexpected error reading request stream")
998
            raise falcon.HTTPError(status=falcon.HTTP_400,
999
                                   title='API.BAD_REQUEST',
1000
                                   description='API.FAILED_TO_READ_REQUEST_STREAM')
1001
1002
        new_values = json.loads(raw_json)
1003
1004
        if 'name' not in new_values['data'].keys() or \
1005
                not isinstance(new_values['data']['name'], str) or \
1006
                len(str.strip(new_values['data']['name'])) == 0:
1007
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
1008
                                   description='API.INVALID_EQUIPMENT_PARAMETER_NAME')
1009
        name = str.strip(new_values['data']['name'])
1010
1011
        if 'parameter_type' not in new_values['data'].keys() or \
1012
                not isinstance(new_values['data']['parameter_type'], str) or \
1013
                len(str.strip(new_values['data']['parameter_type'])) == 0:
1014
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
1015
                                   description='API.INVALID_EQUIPMENT_PARAMETER_TYPE')
1016
1017
        parameter_type = str.strip(new_values['data']['parameter_type'])
1018
1019
        if parameter_type not in ('constant', 'point', 'fraction'):
1020
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
1021
                                   description='API.INVALID_EQUIPMENT_PARAMETER_TYPE')
1022
1023
        constant = None
1024
        if 'constant' in new_values['data'].keys():
1025
            if new_values['data']['constant'] is not None and \
1026
                    isinstance(new_values['data']['constant'], str) and \
1027
                    len(str.strip(new_values['data']['constant'])) > 0:
1028
                constant = str.strip(new_values['data']['constant'])
1029
1030
        point_id = None
1031
        if 'point_id' in new_values['data'].keys():
1032
            if new_values['data']['point_id'] is not None and \
1033
                    new_values['data']['point_id'] <= 0:
1034
                raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
1035
                                       description='API.INVALID_POINT_ID')
1036
            point_id = new_values['data']['point_id']
1037
1038
        numerator_meter_uuid = None
1039
        if 'numerator_meter_uuid' in new_values['data'].keys():
1040
            if new_values['data']['numerator_meter_uuid'] is not None and \
1041
                    isinstance(new_values['data']['numerator_meter_uuid'], str) and \
1042
                    len(str.strip(new_values['data']['numerator_meter_uuid'])) > 0:
1043
                numerator_meter_uuid = str.strip(new_values['data']['numerator_meter_uuid'])
1044
1045
        denominator_meter_uuid = None
1046
        if 'denominator_meter_uuid' in new_values['data'].keys():
1047
            if new_values['data']['denominator_meter_uuid'] is not None and \
1048
                    isinstance(new_values['data']['denominator_meter_uuid'], str) and \
1049
                    len(str.strip(new_values['data']['denominator_meter_uuid'])) > 0:
1050
                denominator_meter_uuid = str.strip(new_values['data']['denominator_meter_uuid'])
1051
1052
        cnx = mysql.connector.connect(**config.myems_system_db)
1053
        cursor = cnx.cursor()
1054
        cursor.execute(" SELECT name "
1055
                       " FROM tbl_equipments "
1056
                       " WHERE id = %s ", (id_,))
1057
        if cursor.fetchone() is None:
1058
            cursor.close()
1059
            cnx.close()
1060
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.NOT_FOUND',
1061
                                   description='API.EQUIPMENT_NOT_FOUND')
1062
1063
        cursor.execute(" SELECT name "
1064
                       " FROM tbl_equipments_parameters "
1065
                       " WHERE name = %s AND equipment_id = %s ", (name, id_))
1066
        if cursor.fetchone() is not None:
1067
            cursor.close()
1068
            cnx.close()
1069
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
1070
                                   description='API.EQUIPMENT_PARAMETER_NAME_IS_ALREADY_IN_USE')
1071
1072
        # validate by parameter type
1073 View Code Duplication
        if parameter_type == 'point':
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
1074
            if point_id is None:
1075
                raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
1076
                                       description='API.INVALID_POINT_ID')
1077
            query = (" SELECT id, name "
1078
                     " FROM tbl_points "
1079
                     " WHERE id = %s ")
1080
            cursor.execute(query, (point_id, ))
1081
            if cursor.fetchone() is None:
1082
                cursor.close()
1083
                cnx.close()
1084
                raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
1085
                                       description='API.POINT_NOT_FOUND')
1086
1087
        elif parameter_type == 'constant':
1088
            if constant is None:
1089
                raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
1090
                                       description='API.INVALID_CONSTANT_VALUE')
1091
1092
        elif parameter_type == 'fraction':
1093
            query = (" SELECT id, name, uuid "
1094
                     " FROM tbl_meters ")
1095
            cursor.execute(query)
1096
            rows_meters = cursor.fetchall()
1097
            meter_dict = dict()
1098
            if rows_meters is not None and len(rows_meters) > 0:
1099
                for row in rows_meters:
1100
                    meter_dict[row[2]] = {"type": 'meter',
1101
                                          "id": row[0],
1102
                                          "name": row[1],
1103
                                          "uuid": row[2]}
1104
1105
            query = (" SELECT id, name, uuid "
1106
                     " FROM tbl_offline_meters ")
1107
            cursor.execute(query)
1108
            rows_offline_meters = cursor.fetchall()
1109
1110
            offline_meter_dict = dict()
1111
            if rows_offline_meters is not None and len(rows_offline_meters) > 0:
1112
                for row in rows_offline_meters:
1113
                    offline_meter_dict[row[2]] = {"type": 'offline_meter',
1114
                                                  "id": row[0],
1115
                                                  "name": row[1],
1116
                                                  "uuid": row[2]}
1117
1118
            query = (" SELECT id, name, uuid "
1119
                     " FROM tbl_virtual_meters ")
1120
            cursor.execute(query)
1121
            rows_virtual_meters = cursor.fetchall()
1122
1123
            virtual_meter_dict = dict()
1124
            if rows_virtual_meters is not None and len(rows_virtual_meters) > 0:
1125
                for row in rows_virtual_meters:
1126
                    virtual_meter_dict[row[2]] = {"type": 'virtual_meter',
1127
                                                  "id": row[0],
1128
                                                  "name": row[1],
1129
                                                  "uuid": row[2]}
1130
1131
            # validate numerator meter uuid
1132
            if meter_dict.get(numerator_meter_uuid) is None and \
1133
                    virtual_meter_dict.get(numerator_meter_uuid) is None and \
1134
                    offline_meter_dict.get(numerator_meter_uuid) is None:
1135
                raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
1136
                                       description='API.INVALID_NUMERATOR_METER_UUID')
1137
1138
            # validate denominator meter uuid
1139
            if denominator_meter_uuid == numerator_meter_uuid:
1140
                raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
1141
                                       description='API.INVALID_DENOMINATOR_METER_UUID')
1142
1143
            if denominator_meter_uuid not in meter_dict and \
1144
                    denominator_meter_uuid not in virtual_meter_dict and \
1145
                    denominator_meter_uuid not in offline_meter_dict:
1146
                raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
1147
                                       description='API.INVALID_DENOMINATOR_METER_UUID')
1148
1149
        add_values = (" INSERT INTO tbl_equipments_parameters "
1150
                      "    (equipment_id, name, parameter_type, constant, "
1151
                      "     point_id, numerator_meter_uuid, denominator_meter_uuid) "
1152
                      " VALUES (%s, %s, %s, %s, %s, %s, %s) ")
1153
        cursor.execute(add_values, (id_,
1154
                                    name,
1155
                                    parameter_type,
1156
                                    constant,
1157
                                    point_id,
1158
                                    numerator_meter_uuid,
1159
                                    denominator_meter_uuid))
1160
        new_id = cursor.lastrowid
1161
        cnx.commit()
1162
        cursor.close()
1163
        cnx.close()
1164
1165
        # Clear cache after creating parameter
1166
        clear_equipment_cache(equipment_id=id_)
1167
1168
        resp.status = falcon.HTTP_201
1169
        resp.location = '/equipments/' + str(id_) + 'parameters/' + str(new_id)
1170
1171
1172
class EquipmentParameterItem:
1173
    @staticmethod
1174
    @user_logger
1175
    def __init__():
1176
        pass
1177
1178
    @staticmethod
1179
    def on_options(req, resp, id_, pid):
1180
        _ = req
1181
        resp.status = falcon.HTTP_200
1182
        _ = id_
1183
        _ = pid
1184
1185
    @staticmethod
1186
    def on_get(req, resp, id_, pid):
1187
        if 'API-KEY' not in req.headers or \
1188
                not isinstance(req.headers['API-KEY'], str) or \
1189
                len(str.strip(req.headers['API-KEY'])) == 0:
1190
            access_control(req)
1191
        else:
1192
            api_key_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_EQUIPMENT_ID')
1196
1197
        if not pid.isdigit() or int(pid) <= 0:
1198
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
1199
                                   description='API.INVALID_EQUIPMENT_PARAMETER_ID')
1200
1201
        cnx = mysql.connector.connect(**config.myems_system_db)
1202
        cursor = cnx.cursor()
1203
1204
        query = (" SELECT id, name "
1205
                 " FROM tbl_points ")
1206
        cursor.execute(query)
1207
        rows_points = cursor.fetchall()
1208
1209
        point_dict = dict()
1210
        if rows_points is not None and len(rows_points) > 0:
1211
            for row in rows_points:
1212
                point_dict[row[0]] = {"id": row[0],
1213
                                      "name": row[1]}
1214
1215
        query = (" SELECT id, name, uuid "
1216
                 " FROM tbl_meters ")
1217
        cursor.execute(query)
1218
        rows_meters = cursor.fetchall()
1219
1220
        meter_dict = dict()
1221
        if rows_meters is not None and len(rows_meters) > 0:
1222
            for row in rows_meters:
1223
                meter_dict[row[2]] = {"type": 'meter',
1224
                                      "id": row[0],
1225
                                      "name": row[1],
1226
                                      "uuid": row[2]}
1227
1228
        query = (" SELECT id, name, uuid "
1229
                 " FROM tbl_offline_meters ")
1230
        cursor.execute(query)
1231
        rows_offline_meters = cursor.fetchall()
1232
1233
        offline_meter_dict = dict()
1234
        if rows_offline_meters is not None and len(rows_offline_meters) > 0:
1235
            for row in rows_offline_meters:
1236
                offline_meter_dict[row[2]] = {"type": 'offline_meter',
1237
                                              "id": row[0],
1238
                                              "name": row[1],
1239
                                              "uuid": row[2]}
1240
1241
        query = (" SELECT id, name, uuid "
1242
                 " FROM tbl_virtual_meters ")
1243
        cursor.execute(query)
1244
        rows_virtual_meters = cursor.fetchall()
1245
1246
        virtual_meter_dict = dict()
1247
        if rows_virtual_meters is not None and len(rows_virtual_meters) > 0:
1248
            for row in rows_virtual_meters:
1249
                virtual_meter_dict[row[2]] = {"type": 'virtual_meter',
1250
                                              "id": row[0],
1251
                                              "name": row[1],
1252
                                              "uuid": row[2]}
1253
1254
        query = (" SELECT id, name, parameter_type, "
1255
                 "        constant, point_id, numerator_meter_uuid, denominator_meter_uuid "
1256
                 " FROM tbl_equipments_parameters "
1257
                 " WHERE equipment_id = %s AND id = %s ")
1258
        cursor.execute(query, (id_, pid))
1259
        row = cursor.fetchone()
1260
        cursor.close()
1261
        cnx.close()
1262
1263
        if row is None:
1264
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
1265
                                   description='API.EQUIPMENT_PARAMETER_NOT_FOUND_OR_NOT_MATCH')
1266
        else:
1267
            constant = None
1268
            point = None
1269
            numerator_meter = None
1270
            denominator_meter = None
1271
            if row[2] == 'point':
1272
                point = point_dict.get(row[4], None)
1273
                constant = None
1274
                numerator_meter = None
1275
                denominator_meter = None
1276
            elif row[2] == 'constant':
1277
                constant = row[3]
1278
                point = None
1279
                numerator_meter = None
1280
                denominator_meter = None
1281
            elif row[2] == 'fraction':
1282
                constant = None
1283
                point = None
1284
                # find numerator meter by uuid
1285
                numerator_meter = meter_dict.get(row[5], None)
1286
                if numerator_meter is None:
1287
                    numerator_meter = virtual_meter_dict.get(row[5], None)
1288
                if numerator_meter is None:
1289
                    numerator_meter = offline_meter_dict.get(row[5], None)
1290
                # find denominator meter by uuid
1291
                denominator_meter = meter_dict.get(row[6], None)
1292
                if denominator_meter is None:
1293
                    denominator_meter = virtual_meter_dict.get(row[6], None)
1294
                if denominator_meter is None:
1295
                    denominator_meter = offline_meter_dict.get(row[6], None)
1296
1297
            meta_result = {"id": row[0],
1298
                           "name": row[1],
1299
                           "parameter_type": row[2],
1300
                           "constant": constant,
1301
                           "point": point,
1302
                           "numerator_meter": numerator_meter,
1303
                           "denominator_meter": denominator_meter}
1304
1305
        resp.text = json.dumps(meta_result)
1306
1307
    @staticmethod
1308
    @user_logger
1309
    def on_delete(req, resp, id_, pid):
1310
        admin_control(req)
1311
        if not id_.isdigit() or int(id_) <= 0:
1312
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
1313
                                   description='API.INVALID_EQUIPMENT_ID')
1314
1315
        if not pid.isdigit() or int(pid) <= 0:
1316
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
1317
                                   description='API.INVALID_EQUIPMENT_PARAMETER_ID')
1318
1319
        cnx = mysql.connector.connect(**config.myems_system_db)
1320
        cursor = cnx.cursor()
1321
1322
        cursor.execute(" SELECT name "
1323
                       " FROM tbl_equipments "
1324
                       " WHERE id = %s ",
1325
                       (id_,))
1326
        row = cursor.fetchone()
1327
        if row is None:
1328
            cursor.close()
1329
            cnx.close()
1330
            raise falcon.HTTPError(status=falcon.HTTP_400,
1331
                                   title='API.NOT_FOUND',
1332
                                   description='API.EQUIPMENT_NOT_FOUND')
1333
1334
        cursor.execute(" SELECT name "
1335
                       " FROM tbl_equipments_parameters "
1336
                       " WHERE equipment_id = %s AND id = %s ",
1337
                       (id_, pid,))
1338
        row = cursor.fetchone()
1339
        if row is None:
1340
            cursor.close()
1341
            cnx.close()
1342
            raise falcon.HTTPError(status=falcon.HTTP_400,
1343
                                   title='API.NOT_FOUND',
1344
                                   description='API.EQUIPMENT_PARAMETER_NOT_FOUND_OR_NOT_MATCH')
1345
1346
        cursor.execute(" DELETE FROM tbl_equipments_parameters "
1347
                       " WHERE id = %s ", (pid, ))
1348
        cnx.commit()
1349
1350
        cursor.close()
1351
        cnx.close()
1352
1353
        # Clear cache after deleting parameter
1354
        clear_equipment_cache(equipment_id=id_)
1355
1356
        resp.status = falcon.HTTP_204
1357
1358
    @staticmethod
1359
    @user_logger
1360
    def on_put(req, resp, id_, pid):
1361
        """Handles PUT requests"""
1362
        admin_control(req)
1363
        if not id_.isdigit() or int(id_) <= 0:
1364
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
1365
                                   description='API.INVALID_EQUIPMENT_ID')
1366
1367
        if not pid.isdigit() or int(pid) <= 0:
1368
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
1369
                                   description='API.INVALID_EQUIPMENT_PARAMETER_ID')
1370
1371
        try:
1372
            raw_json = req.stream.read().decode('utf-8')
1373
        except UnicodeDecodeError as ex:
1374
            print("Failed to decode request")
1375
            raise falcon.HTTPError(status=falcon.HTTP_400,
1376
                                   title='API.BAD_REQUEST',
1377
                                   description='API.INVALID_ENCODING')
1378
        except Exception as ex:
1379
            print("Unexpected error reading request stream")
1380
            raise falcon.HTTPError(status=falcon.HTTP_400,
1381
                                   title='API.BAD_REQUEST',
1382
                                   description='API.FAILED_TO_READ_REQUEST_STREAM')
1383
1384
        new_values = json.loads(raw_json)
1385
1386
        if 'name' not in new_values['data'].keys() or \
1387
                not isinstance(new_values['data']['name'], str) or \
1388
                len(str.strip(new_values['data']['name'])) == 0:
1389
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
1390
                                   description='API.INVALID_EQUIPMENT_PARAMETER_NAME')
1391
        name = str.strip(new_values['data']['name'])
1392
1393
        if 'parameter_type' not in new_values['data'].keys() or \
1394
                not isinstance(new_values['data']['parameter_type'], str) or \
1395
                len(str.strip(new_values['data']['parameter_type'])) == 0:
1396
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
1397
                                   description='API.INVALID_EQUIPMENT_PARAMETER_TYPE')
1398
1399
        parameter_type = str.strip(new_values['data']['parameter_type'])
1400
1401
        if parameter_type not in ('constant', 'point', 'fraction'):
1402
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
1403
                                   description='API.INVALID_EQUIPMENT_PARAMETER_TYPE')
1404
1405
        constant = None
1406
        if 'constant' in new_values['data'].keys():
1407
            if new_values['data']['constant'] is not None and \
1408
                    isinstance(new_values['data']['constant'], str) and \
1409
                    len(str.strip(new_values['data']['constant'])) > 0:
1410
                constant = str.strip(new_values['data']['constant'])
1411
1412
        point_id = None
1413
        if 'point_id' in new_values['data'].keys():
1414
            if new_values['data']['point_id'] is not None and \
1415
                    new_values['data']['point_id'] <= 0:
1416
                raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
1417
                                       description='API.INVALID_POINT_ID')
1418
            point_id = new_values['data']['point_id']
1419
1420
        numerator_meter_uuid = None
1421
        if 'numerator_meter_uuid' in new_values['data'].keys():
1422
            if new_values['data']['numerator_meter_uuid'] is not None and \
1423
                    isinstance(new_values['data']['numerator_meter_uuid'], str) and \
1424
                    len(str.strip(new_values['data']['numerator_meter_uuid'])) > 0:
1425
                numerator_meter_uuid = str.strip(new_values['data']['numerator_meter_uuid'])
1426
1427
        denominator_meter_uuid = None
1428
        if 'denominator_meter_uuid' in new_values['data'].keys():
1429
            if new_values['data']['denominator_meter_uuid'] is not None and \
1430
                    isinstance(new_values['data']['denominator_meter_uuid'], str) and \
1431
                    len(str.strip(new_values['data']['denominator_meter_uuid'])) > 0:
1432
                denominator_meter_uuid = str.strip(new_values['data']['denominator_meter_uuid'])
1433
1434
        cnx = mysql.connector.connect(**config.myems_system_db)
1435
        cursor = cnx.cursor()
1436
1437
        cursor.execute(" SELECT name "
1438
                       " FROM tbl_equipments "
1439
                       " WHERE id = %s ", (id_,))
1440
        if cursor.fetchone() is None:
1441
            cursor.close()
1442
            cnx.close()
1443
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.NOT_FOUND',
1444
                                   description='API.EQUIPMENT_NOT_FOUND')
1445
1446
        cursor.execute(" SELECT name "
1447
                       " FROM tbl_equipments_parameters "
1448
                       " WHERE equipment_id = %s AND id = %s ",
1449
                       (id_, pid,))
1450
        row = cursor.fetchone()
1451
        if row is None:
1452
            cursor.close()
1453
            cnx.close()
1454
            raise falcon.HTTPError(status=falcon.HTTP_400,
1455
                                   title='API.NOT_FOUND',
1456
                                   description='API.EQUIPMENT_PARAMETER_NOT_FOUND_OR_NOT_MATCH')
1457
1458
        cursor.execute(" SELECT name "
1459
                       " FROM tbl_equipments_parameters "
1460
                       " WHERE name = %s AND equipment_id = %s  AND id != %s ", (name, id_, pid))
1461
        row = cursor.fetchone()
1462
        if row is not None:
1463
            cursor.close()
1464
            cnx.close()
1465
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
1466
                                   description='API.EQUIPMENT_PARAMETER_NAME_IS_ALREADY_IN_USE')
1467
1468
        # validate by parameter type
1469 View Code Duplication
        if parameter_type == 'point':
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
1470
            if point_id is None:
1471
                raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
1472
                                       description='API.INVALID_POINT_ID')
1473
1474
            query = (" SELECT id, name "
1475
                     " FROM tbl_points "
1476
                     " WHERE id = %s ")
1477
            cursor.execute(query, (point_id, ))
1478
            row = cursor.fetchone()
1479
            if row is None:
1480
                cursor.close()
1481
                cnx.close()
1482
                raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
1483
                                       description='API.POINT_NOT_FOUND')
1484
1485
        elif parameter_type == 'constant':
1486
            if constant is None:
1487
                raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
1488
                                       description='API.INVALID_CONSTANT_VALUE')
1489
1490
        elif parameter_type == 'fraction':
1491
1492
            query = (" SELECT id, name, uuid "
1493
                     " FROM tbl_meters ")
1494
            cursor.execute(query)
1495
            rows_meters = cursor.fetchall()
1496
1497
            meter_dict = dict()
1498
            if rows_meters is not None and len(rows_meters) > 0:
1499
                for row in rows_meters:
1500
                    meter_dict[row[2]] = {"type": 'meter',
1501
                                          "id": row[0],
1502
                                          "name": row[1],
1503
                                          "uuid": row[2]}
1504
1505
            query = (" SELECT id, name, uuid "
1506
                     " FROM tbl_offline_meters ")
1507
            cursor.execute(query)
1508
            rows_offline_meters = cursor.fetchall()
1509
1510
            offline_meter_dict = dict()
1511
            if rows_offline_meters is not None and len(rows_offline_meters) > 0:
1512
                for row in rows_offline_meters:
1513
                    offline_meter_dict[row[2]] = {"type": 'offline_meter',
1514
                                                  "id": row[0],
1515
                                                  "name": row[1],
1516
                                                  "uuid": row[2]}
1517
1518
            query = (" SELECT id, name, uuid "
1519
                     " FROM tbl_virtual_meters ")
1520
            cursor.execute(query)
1521
            rows_virtual_meters = cursor.fetchall()
1522
1523
            virtual_meter_dict = dict()
1524
            if rows_virtual_meters is not None and len(rows_virtual_meters) > 0:
1525
                for row in rows_virtual_meters:
1526
                    virtual_meter_dict[row[2]] = {"type": 'virtual_meter',
1527
                                                  "id": row[0],
1528
                                                  "name": row[1],
1529
                                                  "uuid": row[2]}
1530
1531
            # validate numerator meter uuid
1532
            if meter_dict.get(numerator_meter_uuid) is None and \
1533
                    virtual_meter_dict.get(numerator_meter_uuid) is None and \
1534
                    offline_meter_dict.get(numerator_meter_uuid) is None:
1535
                raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
1536
                                       description='API.INVALID_NUMERATOR_METER_UUID')
1537
1538
            # validate denominator meter uuid
1539
            if denominator_meter_uuid == numerator_meter_uuid:
1540
                raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
1541
                                       description='API.INVALID_DENOMINATOR_METER_UUID')
1542
1543
            if denominator_meter_uuid not in meter_dict and \
1544
                    denominator_meter_uuid not in virtual_meter_dict and \
1545
                    denominator_meter_uuid not in offline_meter_dict:
1546
                raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
1547
                                       description='API.INVALID_DENOMINATOR_METER_UUID')
1548
1549
        add_values = (" UPDATE tbl_equipments_parameters "
1550
                      " SET name = %s , parameter_type = %s, constant = %s, "
1551
                      "     point_id = %s, numerator_meter_uuid = %s, denominator_meter_uuid = %s "
1552
                      " WHERE id = %s ")
1553
        cursor.execute(add_values, (name,
1554
                                    parameter_type,
1555
                                    constant,
1556
                                    point_id,
1557
                                    numerator_meter_uuid,
1558
                                    denominator_meter_uuid,
1559
                                    pid))
1560
        cnx.commit()
1561
1562
        cursor.close()
1563
        cnx.close()
1564
1565
        # Clear cache after updating parameter
1566
        clear_equipment_cache(equipment_id=id_)
1567
1568
        resp.status = falcon.HTTP_200
1569
1570
1571 View Code Duplication
class EquipmentMeterCollection:
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
1572
    def __init__(self):
1573
        pass
1574
1575
    @staticmethod
1576
    def on_options(req, resp, id_):
1577
        _ = req
1578
        resp.status = falcon.HTTP_200
1579
        _ = id_
1580
1581
    @staticmethod
1582
    def on_get(req, resp, id_):
1583
        if 'API-KEY' not in req.headers or \
1584
                not isinstance(req.headers['API-KEY'], str) or \
1585
                len(str.strip(req.headers['API-KEY'])) == 0:
1586
            access_control(req)
1587
        else:
1588
            api_key_control(req)
1589
        if not id_.isdigit() or int(id_) <= 0:
1590
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
1591
                                   description='API.INVALID_EQUIPMENT_ID')
1592
1593
        cnx = mysql.connector.connect(**config.myems_system_db)
1594
        cursor = cnx.cursor()
1595
1596
        cursor.execute(" SELECT name "
1597
                       " FROM tbl_equipments "
1598
                       " WHERE id = %s ", (id_,))
1599
        if cursor.fetchone() is None:
1600
            cursor.close()
1601
            cnx.close()
1602
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
1603
                                   description='API.EQUIPMENT_NOT_FOUND')
1604
1605
        query = (" SELECT id, name, uuid "
1606
                 " FROM tbl_energy_categories ")
1607
        cursor.execute(query)
1608
        rows_energy_categories = cursor.fetchall()
1609
1610
        energy_category_dict = dict()
1611
        if rows_energy_categories is not None and len(rows_energy_categories) > 0:
1612
            for row in rows_energy_categories:
1613
                energy_category_dict[row[0]] = {"id": row[0],
1614
                                                "name": row[1],
1615
                                                "uuid": row[2]}
1616
1617
        query = (" SELECT m.id, m.name, m.uuid, m.energy_category_id, em.is_output "
1618
                 " FROM tbl_equipments e, tbl_equipments_meters em, tbl_meters m "
1619
                 " WHERE em.equipment_id = e.id AND m.id = em.meter_id AND e.id = %s "
1620
                 " ORDER BY m.id ")
1621
        cursor.execute(query, (id_,))
1622
        rows = cursor.fetchall()
1623
1624
        result = list()
1625
        if rows is not None and len(rows) > 0:
1626
            for row in rows:
1627
                meta_result = {"id": row[0],
1628
                               "name": row[1],
1629
                               "uuid": row[2],
1630
                               "energy_category": energy_category_dict.get(row[3], None),
1631
                               "is_output": bool(row[4])}
1632
                result.append(meta_result)
1633
1634
        resp.text = json.dumps(result)
1635
1636
    @staticmethod
1637
    @user_logger
1638
    def on_post(req, resp, id_):
1639
        """Handles POST requests"""
1640
        admin_control(req)
1641
        try:
1642
            raw_json = req.stream.read().decode('utf-8')
1643
        except UnicodeDecodeError as ex:
1644
            print("Failed to decode request")
1645
            raise falcon.HTTPError(status=falcon.HTTP_400,
1646
                                   title='API.BAD_REQUEST',
1647
                                   description='API.INVALID_ENCODING')
1648
        except Exception as ex:
1649
            print("Unexpected error reading request stream")
1650
            raise falcon.HTTPError(status=falcon.HTTP_400,
1651
                                   title='API.BAD_REQUEST',
1652
                                   description='API.FAILED_TO_READ_REQUEST_STREAM')
1653
1654
        if not id_.isdigit() or int(id_) <= 0:
1655
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
1656
                                   description='API.INVALID_EQUIPMENT_ID')
1657
1658
        new_values = json.loads(raw_json)
1659
1660
        if 'meter_id' not in new_values['data'].keys() or \
1661
                not isinstance(new_values['data']['meter_id'], int) or \
1662
                new_values['data']['meter_id'] <= 0:
1663
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
1664
                                   description='API.INVALID_METER_ID')
1665
        meter_id = new_values['data']['meter_id']
1666
1667
        if 'is_output' not in new_values['data'].keys() or \
1668
                not isinstance(new_values['data']['is_output'], bool):
1669
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
1670
                                   description='API.INVALID_IS_OUTPUT_VALUE')
1671
        is_output = new_values['data']['is_output']
1672
1673
        cnx = mysql.connector.connect(**config.myems_system_db)
1674
        cursor = cnx.cursor()
1675
1676
        cursor.execute(" SELECT name "
1677
                       " from tbl_equipments "
1678
                       " WHERE id = %s ", (id_,))
1679
        if cursor.fetchone() is None:
1680
            cursor.close()
1681
            cnx.close()
1682
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
1683
                                   description='API.EQUIPMENT_NOT_FOUND')
1684
1685
        cursor.execute(" SELECT name "
1686
                       " FROM tbl_meters "
1687
                       " WHERE id = %s ", (meter_id,))
1688
        if cursor.fetchone() is None:
1689
            cursor.close()
1690
            cnx.close()
1691
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
1692
                                   description='API.METER_NOT_FOUND')
1693
1694
        query = (" SELECT id "
1695
                 " FROM tbl_equipments_meters "
1696
                 " WHERE equipment_id = %s AND meter_id = %s")
1697
        cursor.execute(query, (id_, meter_id,))
1698
        if cursor.fetchone() is not None:
1699
            cursor.close()
1700
            cnx.close()
1701
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.ERROR',
1702
                                   description='API.EQUIPMENT_METER_RELATION_EXISTS')
1703
1704
        add_row = (" INSERT INTO tbl_equipments_meters (equipment_id, meter_id, is_output ) "
1705
                   " VALUES (%s, %s, %s) ")
1706
        cursor.execute(add_row, (id_, meter_id, is_output))
1707
        cnx.commit()
1708
        cursor.close()
1709
        cnx.close()
1710
1711
        # Clear cache after adding meter
1712
        clear_equipment_cache(equipment_id=id_)
1713
1714
        resp.status = falcon.HTTP_201
1715
        resp.location = '/equipments/' + str(id_) + '/meters/' + str(meter_id)
1716
1717
1718 View Code Duplication
class EquipmentMeterItem:
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
1719
    def __init__(self):
1720
        pass
1721
1722
    @staticmethod
1723
    def on_options(req, resp, id_, mid):
1724
        _ = req
1725
        resp.status = falcon.HTTP_200
1726
        _ = id_
1727
        _ = mid
1728
1729
    @staticmethod
1730
    @user_logger
1731
    def on_delete(req, resp, id_, mid):
1732
        admin_control(req)
1733
        if not id_.isdigit() or int(id_) <= 0:
1734
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
1735
                                   description='API.INVALID_EQUIPMENT_ID')
1736
1737
        if not mid.isdigit() or int(mid) <= 0:
1738
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
1739
                                   description='API.INVALID_METER_ID')
1740
1741
        cnx = mysql.connector.connect(**config.myems_system_db)
1742
        cursor = cnx.cursor()
1743
1744
        cursor.execute(" SELECT name "
1745
                       " FROM tbl_equipments "
1746
                       " WHERE id = %s ", (id_,))
1747
        if cursor.fetchone() is None:
1748
            cursor.close()
1749
            cnx.close()
1750
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
1751
                                   description='API.EQUIPMENT_NOT_FOUND')
1752
1753
        cursor.execute(" SELECT name "
1754
                       " FROM tbl_meters "
1755
                       " WHERE id = %s ", (mid,))
1756
        if cursor.fetchone() is None:
1757
            cursor.close()
1758
            cnx.close()
1759
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
1760
                                   description='API.METER_NOT_FOUND')
1761
1762
        cursor.execute(" SELECT id "
1763
                       " FROM tbl_equipments_meters "
1764
                       " WHERE equipment_id = %s AND meter_id = %s ", (id_, mid))
1765
        if cursor.fetchone() is None:
1766
            cursor.close()
1767
            cnx.close()
1768
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
1769
                                   description='API.EQUIPMENT_METER_RELATION_NOT_FOUND')
1770
1771
        cursor.execute(" DELETE FROM tbl_equipments_meters WHERE equipment_id = %s AND meter_id = %s ", (id_, mid))
1772
        cnx.commit()
1773
1774
        cursor.close()
1775
        cnx.close()
1776
1777
        # Clear cache after deleting meter
1778
        clear_equipment_cache(equipment_id=id_)
1779
1780
        resp.status = falcon.HTTP_204
1781
1782
1783 View Code Duplication
class EquipmentOfflineMeterCollection:
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
1784
    def __init__(self):
1785
        pass
1786
1787
    @staticmethod
1788
    def on_options(req, resp, id_):
1789
        _ = req
1790
        resp.status = falcon.HTTP_200
1791
        _ = id_
1792
1793
    @staticmethod
1794
    def on_get(req, resp, id_):
1795
        if 'API-KEY' not in req.headers or \
1796
                not isinstance(req.headers['API-KEY'], str) or \
1797
                len(str.strip(req.headers['API-KEY'])) == 0:
1798
            access_control(req)
1799
        else:
1800
            api_key_control(req)
1801
        if not id_.isdigit() or int(id_) <= 0:
1802
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
1803
                                   description='API.INVALID_EQUIPMENT_ID')
1804
1805
        cnx = mysql.connector.connect(**config.myems_system_db)
1806
        cursor = cnx.cursor()
1807
1808
        cursor.execute(" SELECT name "
1809
                       " FROM tbl_equipments "
1810
                       " WHERE id = %s ", (id_,))
1811
        if cursor.fetchone() is None:
1812
            cursor.close()
1813
            cnx.close()
1814
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
1815
                                   description='API.EQUIPMENT_NOT_FOUND')
1816
1817
        query = (" SELECT id, name, uuid "
1818
                 " FROM tbl_energy_categories ")
1819
        cursor.execute(query)
1820
        rows_energy_categories = cursor.fetchall()
1821
1822
        energy_category_dict = dict()
1823
        if rows_energy_categories is not None and len(rows_energy_categories) > 0:
1824
            for row in rows_energy_categories:
1825
                energy_category_dict[row[0]] = {"id": row[0],
1826
                                                "name": row[1],
1827
                                                "uuid": row[2]}
1828
1829
        query = (" SELECT m.id, m.name, m.uuid, m.energy_category_id, em.is_output "
1830
                 " FROM tbl_equipments e, tbl_equipments_offline_meters em, tbl_offline_meters m "
1831
                 " WHERE em.equipment_id = e.id AND m.id = em.offline_meter_id AND e.id = %s "
1832
                 " ORDER BY m.id ")
1833
        cursor.execute(query, (id_,))
1834
        rows = cursor.fetchall()
1835
1836
        result = list()
1837
        if rows is not None and len(rows) > 0:
1838
            for row in rows:
1839
                meta_result = {"id": row[0],
1840
                               "name": row[1],
1841
                               "uuid": row[2],
1842
                               "energy_category": energy_category_dict.get(row[3], None),
1843
                               "is_output": bool(row[4])}
1844
                result.append(meta_result)
1845
1846
        resp.text = json.dumps(result)
1847
1848
    @staticmethod
1849
    @user_logger
1850
    def on_post(req, resp, id_):
1851
        """Handles POST requests"""
1852
        admin_control(req)
1853
        try:
1854
            raw_json = req.stream.read().decode('utf-8')
1855
        except UnicodeDecodeError as ex:
1856
            print("Failed to decode request")
1857
            raise falcon.HTTPError(status=falcon.HTTP_400,
1858
                                   title='API.BAD_REQUEST',
1859
                                   description='API.INVALID_ENCODING')
1860
        except Exception as ex:
1861
            print("Unexpected error reading request stream")
1862
            raise falcon.HTTPError(status=falcon.HTTP_400,
1863
                                   title='API.BAD_REQUEST',
1864
                                   description='API.FAILED_TO_READ_REQUEST_STREAM')
1865
1866
        if not id_.isdigit() or int(id_) <= 0:
1867
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
1868
                                   description='API.INVALID_EQUIPMENT_ID')
1869
1870
        new_values = json.loads(raw_json)
1871
1872
        if 'offline_meter_id' not in new_values['data'].keys() or \
1873
                not isinstance(new_values['data']['offline_meter_id'], int) or \
1874
                new_values['data']['offline_meter_id'] <= 0:
1875
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
1876
                                   description='API.INVALID_OFFLINE_METER_ID')
1877
        offline_meter_id = new_values['data']['offline_meter_id']
1878
1879
        if 'is_output' not in new_values['data'].keys() or \
1880
                not isinstance(new_values['data']['is_output'], bool):
1881
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
1882
                                   description='API.INVALID_IS_OUTPUT_VALUE')
1883
        is_output = new_values['data']['is_output']
1884
1885
        cnx = mysql.connector.connect(**config.myems_system_db)
1886
        cursor = cnx.cursor()
1887
1888
        cursor.execute(" SELECT name "
1889
                       " from tbl_equipments "
1890
                       " WHERE id = %s ", (id_,))
1891
        if cursor.fetchone() is None:
1892
            cursor.close()
1893
            cnx.close()
1894
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
1895
                                   description='API.EQUIPMENT_NOT_FOUND')
1896
1897
        cursor.execute(" SELECT name "
1898
                       " FROM tbl_offline_meters "
1899
                       " WHERE id = %s ", (offline_meter_id,))
1900
        if cursor.fetchone() is None:
1901
            cursor.close()
1902
            cnx.close()
1903
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
1904
                                   description='API.OFFLINE_METER_NOT_FOUND')
1905
1906
        query = (" SELECT id "
1907
                 " FROM tbl_equipments_offline_meters "
1908
                 " WHERE equipment_id = %s AND offline_meter_id = %s")
1909
        cursor.execute(query, (id_, offline_meter_id,))
1910
        if cursor.fetchone() is not None:
1911
            cursor.close()
1912
            cnx.close()
1913
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.ERROR',
1914
                                   description='API.EQUIPMENT_OFFLINE_METER_RELATION_EXISTS')
1915
1916
        add_row = (" INSERT INTO tbl_equipments_offline_meters (equipment_id, offline_meter_id, is_output ) "
1917
                   " VALUES (%s, %s, %s) ")
1918
        cursor.execute(add_row, (id_, offline_meter_id, is_output))
1919
        cnx.commit()
1920
        cursor.close()
1921
        cnx.close()
1922
1923
        # Clear cache after adding offline meter
1924
        clear_equipment_cache(equipment_id=id_)
1925
1926
        resp.status = falcon.HTTP_201
1927
        resp.location = '/equipments/' + str(id_) + '/offlinemeters/' + str(offline_meter_id)
1928
1929
1930 View Code Duplication
class EquipmentOfflineMeterItem:
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
1931
    def __init__(self):
1932
        pass
1933
1934
    @staticmethod
1935
    def on_options(req, resp, id_, mid):
1936
        _ = req
1937
        resp.status = falcon.HTTP_200
1938
        _ = id_
1939
        _ = mid
1940
1941
    @staticmethod
1942
    @user_logger
1943
    def on_delete(req, resp, id_, mid):
1944
        admin_control(req)
1945
        if not id_.isdigit() or int(id_) <= 0:
1946
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
1947
                                   description='API.INVALID_EQUIPMENT_ID')
1948
1949
        if not mid.isdigit() or int(mid) <= 0:
1950
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
1951
                                   description='API.INVALID_OFFLINE_METER_ID')
1952
1953
        cnx = mysql.connector.connect(**config.myems_system_db)
1954
        cursor = cnx.cursor()
1955
1956
        cursor.execute(" SELECT name "
1957
                       " FROM tbl_equipments "
1958
                       " WHERE id = %s ", (id_,))
1959
        if cursor.fetchone() is None:
1960
            cursor.close()
1961
            cnx.close()
1962
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
1963
                                   description='API.EQUIPMENT_NOT_FOUND')
1964
1965
        cursor.execute(" SELECT name "
1966
                       " FROM tbl_offline_meters "
1967
                       " WHERE id = %s ", (mid,))
1968
        if cursor.fetchone() is None:
1969
            cursor.close()
1970
            cnx.close()
1971
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
1972
                                   description='API.OFFLINE_METER_NOT_FOUND')
1973
1974
        cursor.execute(" SELECT id "
1975
                       " FROM tbl_equipments_offline_meters "
1976
                       " WHERE equipment_id = %s AND offline_meter_id = %s ", (id_, mid))
1977
        if cursor.fetchone() is None:
1978
            cursor.close()
1979
            cnx.close()
1980
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
1981
                                   description='API.EQUIPMENT_OFFLINE_METER_RELATION_NOT_FOUND')
1982
1983
        cursor.execute(" DELETE FROM tbl_equipments_offline_meters "
1984
                       " WHERE equipment_id = %s AND offline_meter_id = %s ", (id_, mid))
1985
        cnx.commit()
1986
1987
        cursor.close()
1988
        cnx.close()
1989
1990
        # Clear cache after deleting offline meter
1991
        clear_equipment_cache(equipment_id=id_)
1992
1993
        resp.status = falcon.HTTP_204
1994
1995
1996 View Code Duplication
class EquipmentVirtualMeterCollection:
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
1997
    def __init__(self):
1998
        pass
1999
2000
    @staticmethod
2001
    def on_options(req, resp, id_):
2002
        _ = req
2003
        resp.status = falcon.HTTP_200
2004
        _ = id_
2005
2006
    @staticmethod
2007
    def on_get(req, resp, id_):
2008
        if 'API-KEY' not in req.headers or \
2009
                not isinstance(req.headers['API-KEY'], str) or \
2010
                len(str.strip(req.headers['API-KEY'])) == 0:
2011
            access_control(req)
2012
        else:
2013
            api_key_control(req)
2014
        if not id_.isdigit() or int(id_) <= 0:
2015
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
2016
                                   description='API.INVALID_EQUIPMENT_ID')
2017
2018
        cnx = mysql.connector.connect(**config.myems_system_db)
2019
        cursor = cnx.cursor()
2020
2021
        cursor.execute(" SELECT name "
2022
                       " FROM tbl_equipments "
2023
                       " WHERE id = %s ", (id_,))
2024
        if cursor.fetchone() is None:
2025
            cursor.close()
2026
            cnx.close()
2027
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
2028
                                   description='API.EQUIPMENT_NOT_FOUND')
2029
2030
        query = (" SELECT id, name, uuid "
2031
                 " FROM tbl_energy_categories ")
2032
        cursor.execute(query)
2033
        rows_energy_categories = cursor.fetchall()
2034
2035
        energy_category_dict = dict()
2036
        if rows_energy_categories is not None and len(rows_energy_categories) > 0:
2037
            for row in rows_energy_categories:
2038
                energy_category_dict[row[0]] = {"id": row[0],
2039
                                                "name": row[1],
2040
                                                "uuid": row[2]}
2041
2042
        query = (" SELECT m.id, m.name, m.uuid, m.energy_category_id, em.is_output "
2043
                 " FROM tbl_equipments e, tbl_equipments_virtual_meters em, tbl_virtual_meters m "
2044
                 " WHERE em.equipment_id = e.id AND m.id = em.virtual_meter_id AND e.id = %s "
2045
                 " ORDER BY m.id ")
2046
        cursor.execute(query, (id_,))
2047
        rows = cursor.fetchall()
2048
2049
        result = list()
2050
        if rows is not None and len(rows) > 0:
2051
            for row in rows:
2052
                meta_result = {"id": row[0],
2053
                               "name": row[1],
2054
                               "uuid": row[2],
2055
                               "energy_category": energy_category_dict.get(row[3], None),
2056
                               "is_output": bool(row[4])}
2057
                result.append(meta_result)
2058
2059
        resp.text = json.dumps(result)
2060
2061
    @staticmethod
2062
    @user_logger
2063
    def on_post(req, resp, id_):
2064
        """Handles POST requests"""
2065
        admin_control(req)
2066
        try:
2067
            raw_json = req.stream.read().decode('utf-8')
2068
        except UnicodeDecodeError as ex:
2069
            print("Failed to decode request")
2070
            raise falcon.HTTPError(status=falcon.HTTP_400,
2071
                                   title='API.BAD_REQUEST',
2072
                                   description='API.INVALID_ENCODING')
2073
        except Exception as ex:
2074
            print("Unexpected error reading request stream")
2075
            raise falcon.HTTPError(status=falcon.HTTP_400,
2076
                                   title='API.BAD_REQUEST',
2077
                                   description='API.FAILED_TO_READ_REQUEST_STREAM')
2078
2079
        if not id_.isdigit() or int(id_) <= 0:
2080
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
2081
                                   description='API.INVALID_EQUIPMENT_ID')
2082
2083
        new_values = json.loads(raw_json)
2084
2085
        if 'virtual_meter_id' not in new_values['data'].keys() or \
2086
                not isinstance(new_values['data']['virtual_meter_id'], int) or \
2087
                new_values['data']['virtual_meter_id'] <= 0:
2088
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
2089
                                   description='API.INVALID_VIRTUAL_METER_ID')
2090
        virtual_meter_id = new_values['data']['virtual_meter_id']
2091
2092
        if 'is_output' not in new_values['data'].keys() or \
2093
                not isinstance(new_values['data']['is_output'], bool):
2094
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
2095
                                   description='API.INVALID_IS_OUTPUT_VALUE')
2096
        is_output = new_values['data']['is_output']
2097
2098
        cnx = mysql.connector.connect(**config.myems_system_db)
2099
        cursor = cnx.cursor()
2100
2101
        cursor.execute(" SELECT name "
2102
                       " from tbl_equipments "
2103
                       " WHERE id = %s ", (id_,))
2104
        if cursor.fetchone() is None:
2105
            cursor.close()
2106
            cnx.close()
2107
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
2108
                                   description='API.EQUIPMENT_NOT_FOUND')
2109
2110
        cursor.execute(" SELECT name "
2111
                       " FROM tbl_virtual_meters "
2112
                       " WHERE id = %s ", (virtual_meter_id,))
2113
        if cursor.fetchone() is None:
2114
            cursor.close()
2115
            cnx.close()
2116
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
2117
                                   description='API.VIRTUAL_METER_NOT_FOUND')
2118
2119
        query = (" SELECT id "
2120
                 " FROM tbl_equipments_virtual_meters "
2121
                 " WHERE equipment_id = %s AND virtual_meter_id = %s")
2122
        cursor.execute(query, (id_, virtual_meter_id,))
2123
        if cursor.fetchone() is not None:
2124
            cursor.close()
2125
            cnx.close()
2126
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.ERROR',
2127
                                   description='API.EQUIPMENT_VIRTUAL_METER_RELATION_EXISTS')
2128
2129
        add_row = (" INSERT INTO tbl_equipments_virtual_meters (equipment_id, virtual_meter_id, is_output ) "
2130
                   " VALUES (%s, %s, %s) ")
2131
        cursor.execute(add_row, (id_, virtual_meter_id, is_output))
2132
        cnx.commit()
2133
        cursor.close()
2134
        cnx.close()
2135
2136
        # Clear cache after adding virtual meter
2137
        clear_equipment_cache(equipment_id=id_)
2138
2139
        resp.status = falcon.HTTP_201
2140
        resp.location = '/equipments/' + str(id_) + '/virtualmeters/' + str(virtual_meter_id)
2141
2142
2143 View Code Duplication
class EquipmentVirtualMeterItem:
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
2144
    def __init__(self):
2145
        pass
2146
2147
    @staticmethod
2148
    def on_options(req, resp, id_, mid):
2149
        _ = req
2150
        resp.status = falcon.HTTP_200
2151
        _ = id_
2152
        _ = mid
2153
2154
    @staticmethod
2155
    @user_logger
2156
    def on_delete(req, resp, id_, mid):
2157
        admin_control(req)
2158
        if not id_.isdigit() or int(id_) <= 0:
2159
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
2160
                                   description='API.INVALID_EQUIPMENT_ID')
2161
2162
        if not mid.isdigit() or int(mid) <= 0:
2163
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
2164
                                   description='API.INVALID_VIRTUAL_METER_ID')
2165
2166
        cnx = mysql.connector.connect(**config.myems_system_db)
2167
        cursor = cnx.cursor()
2168
2169
        cursor.execute(" SELECT name "
2170
                       " FROM tbl_equipments "
2171
                       " WHERE id = %s ", (id_,))
2172
        if cursor.fetchone() is None:
2173
            cursor.close()
2174
            cnx.close()
2175
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
2176
                                   description='API.EQUIPMENT_NOT_FOUND')
2177
2178
        cursor.execute(" SELECT name "
2179
                       " FROM tbl_virtual_meters "
2180
                       " WHERE id = %s ", (mid,))
2181
        if cursor.fetchone() is None:
2182
            cursor.close()
2183
            cnx.close()
2184
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
2185
                                   description='API.VIRTUAL_METER_NOT_FOUND')
2186
2187
        cursor.execute(" SELECT id "
2188
                       " FROM tbl_equipments_virtual_meters "
2189
                       " WHERE equipment_id = %s AND virtual_meter_id = %s ", (id_, mid))
2190
        if cursor.fetchone() is None:
2191
            cursor.close()
2192
            cnx.close()
2193
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
2194
                                   description='API.EQUIPMENT_VIRTUAL_METER_RELATION_NOT_FOUND')
2195
2196
        cursor.execute(" DELETE FROM tbl_equipments_virtual_meters "
2197
                       " WHERE equipment_id = %s AND virtual_meter_id = %s ", (id_, mid))
2198
        cnx.commit()
2199
2200
        cursor.close()
2201
        cnx.close()
2202
2203
        # Clear cache after deleting virtual meter
2204
        clear_equipment_cache(equipment_id=id_)
2205
2206
        resp.status = falcon.HTTP_204
2207
2208
2209 View Code Duplication
class EquipmentCommandCollection:
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
2210
    def __init__(self):
2211
        pass
2212
2213
    @staticmethod
2214
    def on_options(req, resp, id_):
2215
        _ = req
2216
        resp.status = falcon.HTTP_200
2217
        _ = id_
2218
2219
    @staticmethod
2220
    def on_get(req, resp, id_):
2221
        if 'API-KEY' not in req.headers or \
2222
                not isinstance(req.headers['API-KEY'], str) or \
2223
                len(str.strip(req.headers['API-KEY'])) == 0:
2224
            access_control(req)
2225
        else:
2226
            api_key_control(req)
2227
        if not id_.isdigit() or int(id_) <= 0:
2228
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
2229
                                   description='API.INVALID_EQUIPMENT_ID')
2230
2231
        cnx = mysql.connector.connect(**config.myems_system_db)
2232
        cursor = cnx.cursor()
2233
2234
        cursor.execute(" SELECT name "
2235
                       " FROM tbl_equipments "
2236
                       " WHERE id = %s ", (id_,))
2237
        if cursor.fetchone() is None:
2238
            cursor.close()
2239
            cnx.close()
2240
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
2241
                                   description='API.EQUIPMENT_NOT_FOUND')
2242
2243
        query = (" SELECT c.id, c.name, c.uuid "
2244
                 " FROM tbl_equipments e, tbl_equipments_commands ec, tbl_commands c "
2245
                 " WHERE ec.equipment_id = e.id AND c.id = ec.command_id AND e.id = %s "
2246
                 " ORDER BY c.id ")
2247
        cursor.execute(query, (id_,))
2248
        rows = cursor.fetchall()
2249
2250
        result = list()
2251
        if rows is not None and len(rows) > 0:
2252
            for row in rows:
2253
                meta_result = {"id": row[0],
2254
                               "name": row[1],
2255
                               "uuid": row[2]}
2256
                result.append(meta_result)
2257
2258
        resp.text = json.dumps(result)
2259
2260
    @staticmethod
2261
    @user_logger
2262
    def on_post(req, resp, id_):
2263
        """Handles POST requests"""
2264
        admin_control(req)
2265
        try:
2266
            raw_json = req.stream.read().decode('utf-8')
2267
        except UnicodeDecodeError as ex:
2268
            print("Failed to decode request")
2269
            raise falcon.HTTPError(status=falcon.HTTP_400,
2270
                                   title='API.BAD_REQUEST',
2271
                                   description='API.INVALID_ENCODING')
2272
        except Exception as ex:
2273
            print("Unexpected error reading request stream")
2274
            raise falcon.HTTPError(status=falcon.HTTP_400,
2275
                                   title='API.BAD_REQUEST',
2276
                                   description='API.FAILED_TO_READ_REQUEST_STREAM')
2277
2278
        if not id_.isdigit() or int(id_) <= 0:
2279
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
2280
                                   description='API.INVALID_EQUIPMENT_ID')
2281
2282
        new_values = json.loads(raw_json)
2283
2284
        if 'command_id' not in new_values['data'].keys() or \
2285
                not isinstance(new_values['data']['command_id'], int) or \
2286
                new_values['data']['command_id'] <= 0:
2287
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
2288
                                   description='API.INVALID_COMMAND_ID')
2289
        command_id = new_values['data']['command_id']
2290
2291
        cnx = mysql.connector.connect(**config.myems_system_db)
2292
        cursor = cnx.cursor()
2293
2294
        cursor.execute(" SELECT name "
2295
                       " from tbl_equipments "
2296
                       " WHERE id = %s ", (id_,))
2297
        if cursor.fetchone() is None:
2298
            cursor.close()
2299
            cnx.close()
2300
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
2301
                                   description='API.EQUIPMENT_NOT_FOUND')
2302
2303
        cursor.execute(" SELECT name "
2304
                       " FROM tbl_commands "
2305
                       " WHERE id = %s ", (command_id,))
2306
        if cursor.fetchone() is None:
2307
            cursor.close()
2308
            cnx.close()
2309
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
2310
                                   description='API.COMMAND_NOT_FOUND')
2311
2312
        query = (" SELECT id "
2313
                 " FROM tbl_equipments_commands "
2314
                 " WHERE equipment_id = %s AND command_id = %s")
2315
        cursor.execute(query, (id_, command_id,))
2316
        if cursor.fetchone() is not None:
2317
            cursor.close()
2318
            cnx.close()
2319
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.ERROR',
2320
                                   description='API.EQUIPMENT_COMMAND_RELATION_EXISTS')
2321
2322
        add_row = (" INSERT INTO tbl_equipments_commands (equipment_id, command_id) "
2323
                   " VALUES (%s, %s) ")
2324
        cursor.execute(add_row, (id_, command_id,))
2325
        cnx.commit()
2326
        cursor.close()
2327
        cnx.close()
2328
2329
        # Clear cache after adding command
2330
        clear_equipment_cache(equipment_id=id_)
2331
2332
        resp.status = falcon.HTTP_201
2333
        resp.location = '/equipments/' + str(id_) + '/commands/' + str(command_id)
2334
2335
2336 View Code Duplication
class EquipmentCommandItem:
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
2337
    def __init__(self):
2338
        pass
2339
2340
    @staticmethod
2341
    def on_options(req, resp, id_, cid):
2342
        _ = req
2343
        resp.status = falcon.HTTP_200
2344
        _ = id_
2345
        _ = cid
2346
2347
    @staticmethod
2348
    @user_logger
2349
    def on_delete(req, resp, id_, cid):
2350
        admin_control(req)
2351
        if not id_.isdigit() or int(id_) <= 0:
2352
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
2353
                                   description='API.INVALID_EQUIPMENT_ID')
2354
2355
        if not cid.isdigit() or int(cid) <= 0:
2356
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
2357
                                   description='API.INVALID_COMMAND_ID')
2358
2359
        cnx = mysql.connector.connect(**config.myems_system_db)
2360
        cursor = cnx.cursor()
2361
2362
        cursor.execute(" SELECT name "
2363
                       " FROM tbl_equipments "
2364
                       " WHERE id = %s ", (id_,))
2365
        if cursor.fetchone() is None:
2366
            cursor.close()
2367
            cnx.close()
2368
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
2369
                                   description='API.EQUIPMENT_NOT_FOUND')
2370
2371
        cursor.execute(" SELECT name "
2372
                       " FROM tbl_commands "
2373
                       " WHERE id = %s ", (cid,))
2374
        if cursor.fetchone() is None:
2375
            cursor.close()
2376
            cnx.close()
2377
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
2378
                                   description='API.COMMAND_NOT_FOUND')
2379
2380
        cursor.execute(" SELECT id "
2381
                       " FROM tbl_equipments_commands "
2382
                       " WHERE equipment_id = %s AND command_id = %s ", (id_, cid))
2383
        if cursor.fetchone() is None:
2384
            cursor.close()
2385
            cnx.close()
2386
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
2387
                                   description='API.EQUIPMENT_COMMAND_RELATION_NOT_FOUND')
2388
2389
        cursor.execute(" DELETE FROM tbl_equipments_commands WHERE equipment_id = %s AND command_id = %s ", (id_, cid))
2390
        cnx.commit()
2391
2392
        cursor.close()
2393
        cnx.close()
2394
2395
        # Clear cache after deleting command
2396
        clear_equipment_cache(equipment_id=id_)
2397
2398
        resp.status = falcon.HTTP_204
2399
2400
2401
class EquipmentExport:
2402
    def __init__(self):
2403
        pass
2404
2405
    @staticmethod
2406
    def on_options(req, resp, id_):
2407
        _ = req
2408
        resp.status = falcon.HTTP_200
2409
        _ = id_
2410
2411
    @staticmethod
2412
    def on_get(req, resp, id_):
2413
        if 'API-KEY' not in req.headers or \
2414
                not isinstance(req.headers['API-KEY'], str) or \
2415
                len(str.strip(req.headers['API-KEY'])) == 0:
2416
            access_control(req)
2417
        else:
2418
            api_key_control(req)
2419
        if not id_.isdigit() or int(id_) <= 0:
2420
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
2421
                                   description='API.INVALID_EQUIPMENT_ID')
2422
2423
        cnx = mysql.connector.connect(**config.myems_system_db)
2424
        cursor = cnx.cursor()
2425
2426
        query = (" SELECT id, name, uuid "
2427
                 " FROM tbl_cost_centers ")
2428
        cursor.execute(query)
2429
        rows_cost_centers = cursor.fetchall()
2430
2431
        cost_center_dict = dict()
2432
        if rows_cost_centers is not None and len(rows_cost_centers) > 0:
2433
            for row in rows_cost_centers:
2434
                cost_center_dict[row[0]] = {"id": row[0],
2435
                                            "name": row[1],
2436
                                            "uuid": row[2]}
2437
2438
        query = (" SELECT id, name, uuid "
2439
                 " FROM tbl_svgs ")
2440
        cursor.execute(query)
2441
        rows_svgs = cursor.fetchall()
2442
2443
        svg_dict = dict()
2444
        if rows_svgs is not None and len(rows_svgs) > 0:
2445
            for row in rows_svgs:
2446
                svg_dict[row[0]] = {"id": row[0],
2447
                                    "name": row[1],
2448
                                    "uuid": row[2]}
2449
2450
        query = (" SELECT id, name, uuid, "
2451
                 "        is_input_counted, is_output_counted, "
2452
                 "        cost_center_id, svg_id, camera_url, description "
2453
                 " FROM tbl_equipments "
2454
                 " WHERE id = %s ")
2455
        cursor.execute(query, (id_,))
2456
        row = cursor.fetchone()
2457
2458
        if row is None:
2459
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
2460
                                   description='API.EQUIPMENT_NOT_FOUND')
2461
        else:
2462
            meta_result = {"id": row[0],
2463
                           "name": row[1],
2464
                           "uuid": row[2],
2465
                           "is_input_counted": bool(row[3]),
2466
                           "is_output_counted": bool(row[4]),
2467
                           "cost_center": cost_center_dict.get(row[5], None),
2468
                           "svg": svg_dict.get(row[6], None),
2469
                           "camera_url": row[7],
2470
                           "description": row[8],
2471
                           "commands": None,
2472
                           "meters": None,
2473
                           "offline_meters": None,
2474
                           "virtual_meters": None,
2475
                           "parameters": None}
2476
2477
            query = (" SELECT c.id, c.name, c.uuid "
2478
                     " FROM tbl_equipments e, tbl_equipments_commands ec, tbl_commands c "
2479
                     " WHERE ec.equipment_id = e.id AND c.id = ec.command_id AND e.id = %s "
2480
                     " ORDER BY c.id ")
2481
            cursor.execute(query, (id_,))
2482
            rows = cursor.fetchall()
2483
2484
            command_result = list()
2485
            if rows is not None and len(rows) > 0:
2486
                for row in rows:
2487
                    result = {"id": row[0],
2488
                              "name": row[1],
2489
                              "uuid": row[2]}
2490
                    command_result.append(result)
2491
                meta_result['commands'] = command_result
2492
2493
            query = (" SELECT id, name, uuid "
2494
                     " FROM tbl_energy_categories ")
2495
            cursor.execute(query)
2496
            rows_energy_categories = cursor.fetchall()
2497
2498
            energy_category_dict = dict()
2499
            if rows_energy_categories is not None and len(rows_energy_categories) > 0:
2500
                for row in rows_energy_categories:
2501
                    energy_category_dict[row[0]] = {"id": row[0],
2502
                                                    "name": row[1],
2503
                                                    "uuid": row[2]}
2504
2505
            query = (" SELECT m.id, m.name, m.uuid, m.energy_category_id, em.is_output "
2506
                     " FROM tbl_equipments e, tbl_equipments_meters em, tbl_meters m "
2507
                     " WHERE em.equipment_id = e.id AND m.id = em.meter_id AND e.id = %s "
2508
                     " ORDER BY m.id ")
2509
            cursor.execute(query, (id_,))
2510
            rows = cursor.fetchall()
2511
2512
            meter_result = list()
2513
            if rows is not None and len(rows) > 0:
2514
                for row in rows:
2515
                    result = {"id": row[0],
2516
                              "name": row[1],
2517
                              "uuid": row[2],
2518
                              "energy_category": energy_category_dict.get(row[3], None),
2519
                              "is_output": bool(row[4])}
2520
                    meter_result.append(result)
2521
                meta_result['meters'] = meter_result
2522
            query = (" SELECT m.id, m.name, m.uuid, m.energy_category_id, em.is_output "
2523
                     " FROM tbl_equipments e, tbl_equipments_offline_meters em, tbl_offline_meters m "
2524
                     " WHERE em.equipment_id = e.id AND m.id = em.offline_meter_id AND e.id = %s "
2525
                     " ORDER BY m.id ")
2526
            cursor.execute(query, (id_,))
2527
            rows = cursor.fetchall()
2528
2529
            offlinemeter_result = list()
2530
            if rows is not None and len(rows) > 0:
2531
                for row in rows:
2532
                    result = {"id": row[0],
2533
                              "name": row[1],
2534
                              "uuid": row[2],
2535
                              "energy_category": energy_category_dict.get(row[3], None),
2536
                              "is_output": bool(row[4])}
2537
                    offlinemeter_result.append(result)
2538
                meta_result['offline_meters'] = offlinemeter_result
2539
            query = (" SELECT m.id, m.name, m.uuid, m.energy_category_id, em.is_output "
2540
                     " FROM tbl_equipments e, tbl_equipments_virtual_meters em, tbl_virtual_meters m "
2541
                     " WHERE em.equipment_id = e.id AND m.id = em.virtual_meter_id AND e.id = %s "
2542
                     " ORDER BY m.id ")
2543
            cursor.execute(query, (id_,))
2544
            rows = cursor.fetchall()
2545
2546
            virtualmeter_result = list()
2547
            if rows is not None and len(rows) > 0:
2548
                for row in rows:
2549
                    result = {"id": row[0],
2550
                              "name": row[1],
2551
                              "uuid": row[2],
2552
                              "energy_category": energy_category_dict.get(row[3], None),
2553
                              "is_output": bool(row[4])}
2554
                    virtualmeter_result.append(result)
2555
                meta_result['virtual_meters'] = virtualmeter_result
2556
            query = (" SELECT id, name "
2557
                     " FROM tbl_points ")
2558
            cursor.execute(query)
2559
            rows_points = cursor.fetchall()
2560
2561
            point_dict = dict()
2562
            if rows_points is not None and len(rows_points) > 0:
2563
                for row in rows_points:
2564
                    point_dict[row[0]] = {"id": row[0],
2565
                                          "name": row[1]}
2566
2567
            query = (" SELECT id, name, uuid "
2568
                     " FROM tbl_meters ")
2569
            cursor.execute(query)
2570
            rows_meters = cursor.fetchall()
2571
2572
            meter_dict = dict()
2573
            if rows_meters is not None and len(rows_meters) > 0:
2574
                for row in rows_meters:
2575
                    meter_dict[row[2]] = {"type": 'meter',
2576
                                          "id": row[0],
2577
                                          "name": row[1],
2578
                                          "uuid": row[2]}
2579
2580
            query = (" SELECT id, name, uuid "
2581
                     " FROM tbl_offline_meters ")
2582
            cursor.execute(query)
2583
            rows_offline_meters = cursor.fetchall()
2584
2585
            offline_meter_dict = dict()
2586
            if rows_offline_meters is not None and len(rows_offline_meters) > 0:
2587
                for row in rows_offline_meters:
2588
                    offline_meter_dict[row[2]] = {"type": 'offline_meter',
2589
                                                  "id": row[0],
2590
                                                  "name": row[1],
2591
                                                  "uuid": row[2]}
2592
2593
            query = (" SELECT id, name, uuid "
2594
                     " FROM tbl_virtual_meters ")
2595
            cursor.execute(query)
2596
            rows_virtual_meters = cursor.fetchall()
2597
2598
            virtual_meter_dict = dict()
2599
            if rows_virtual_meters is not None and len(rows_virtual_meters) > 0:
2600
                for row in rows_virtual_meters:
2601
                    virtual_meter_dict[row[2]] = {"type": 'virtual_meter',
2602
                                                  "id": row[0],
2603
                                                  "name": row[1],
2604
                                                  "uuid": row[2]}
2605
2606
            query = (" SELECT id, name, parameter_type, "
2607
                     "        constant, point_id, numerator_meter_uuid, denominator_meter_uuid "
2608
                     " FROM tbl_equipments_parameters "
2609
                     " WHERE equipment_id = %s "
2610
                     " ORDER BY id ")
2611
            cursor.execute(query, (id_,))
2612
            rows_parameters = cursor.fetchall()
2613
2614
            parameters_result = list()
2615 View Code Duplication
            if rows_parameters is not None and len(rows_parameters) > 0:
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
2616
                for row in rows_parameters:
2617
                    constant = None
2618
                    point = None
2619
                    numerator_meter = None
2620
                    denominator_meter = None
2621
                    if row[2] == 'point':
2622
                        point = point_dict.get(row[4], None)
2623
                        constant = None
2624
                        numerator_meter = None
2625
                        denominator_meter = None
2626
                    elif row[2] == 'constant':
2627
                        constant = row[3]
2628
                        point = None
2629
                        numerator_meter = None
2630
                        denominator_meter = None
2631
                    elif row[2] == 'fraction':
2632
                        constant = None
2633
                        point = None
2634
                        # find numerator meter by uuid
2635
                        numerator_meter = meter_dict.get(row[5], None)
2636
                        if numerator_meter is None:
2637
                            numerator_meter = virtual_meter_dict.get(row[5], None)
2638
                        if numerator_meter is None:
2639
                            numerator_meter = offline_meter_dict.get(row[5], None)
2640
                        # find denominator meter by uuid
2641
                        denominator_meter = meter_dict.get(row[6], None)
2642
                        if denominator_meter is None:
2643
                            denominator_meter = virtual_meter_dict.get(row[6], None)
2644
                        if denominator_meter is None:
2645
                            denominator_meter = offline_meter_dict.get(row[6], None)
2646
2647
                    result = {"id": row[0],
2648
                              "name": row[1],
2649
                              "parameter_type": row[2],
2650
                              "constant": constant,
2651
                              "point": point,
2652
                              "numerator_meter": numerator_meter,
2653
                              "denominator_meter": denominator_meter}
2654
                    parameters_result.append(result)
2655
                meta_result['parameters'] = parameters_result
2656
2657
        cursor.close()
2658
        cnx.close()
2659
        resp.text = json.dumps(meta_result)
2660
2661
2662
class EquipmentImport:
2663
    def __init__(self):
2664
        pass
2665
2666
    @staticmethod
2667
    def on_options(req, resp):
2668
        _ = req
2669
        resp.status = falcon.HTTP_200
2670
2671
    @staticmethod
2672
    def on_post(req, resp):
2673
        """Handles POST requests"""
2674
        admin_control(req)
2675
        try:
2676
            raw_json = req.stream.read().decode('utf-8')
2677
        except UnicodeDecodeError as ex:
2678
            print("Failed to decode request")
2679
            raise falcon.HTTPError(status=falcon.HTTP_400,
2680
                                   title='API.BAD_REQUEST',
2681
                                   description='API.INVALID_ENCODING')
2682
        except Exception as ex:
2683
            print("Unexpected error reading request stream")
2684
            raise falcon.HTTPError(status=falcon.HTTP_400,
2685
                                   title='API.BAD_REQUEST',
2686
                                   description='API.FAILED_TO_READ_REQUEST_STREAM')
2687
2688
        new_values = json.loads(raw_json)
2689
2690
        if 'name' not in new_values.keys() or \
2691
                not isinstance(new_values['name'], str) or \
2692
                len(str.strip(new_values['name'])) == 0:
2693
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
2694
                                   description='API.INVALID_EQUIPMENT_NAME')
2695
        name = str.strip(new_values['name'])
2696
2697
        if 'is_input_counted' not in new_values.keys() or \
2698
                not isinstance(new_values['is_input_counted'], bool):
2699
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
2700
                                   description='API.INVALID_IS_INPUT_COUNTED_VALUE')
2701
        is_input_counted = new_values['is_input_counted']
2702
2703
        if 'is_output_counted' not in new_values.keys() or \
2704
                not isinstance(new_values['is_output_counted'], bool):
2705
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
2706
                                   description='API.INVALID_IS_OUTPUT_COUNTED_VALUE')
2707
        is_output_counted = new_values['is_output_counted']
2708
2709
        if 'id' not in new_values['cost_center'].keys() or \
2710
                not isinstance(new_values['cost_center']['id'], int) or \
2711
                new_values['cost_center']['id'] <= 0:
2712
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
2713
                                   description='API.INVALID_COST_CENTER_ID')
2714
        cost_center_id = new_values['cost_center']['id']
2715
2716
        svg = new_values.get('svg', None)
2717
        svg_id = None
2718
        if isinstance(svg, dict):
2719
            svg_id = svg.get('id', None)
2720
            if not (isinstance(svg_id, int) and svg_id > 0):
2721
                svg_id = None
2722
2723
        if 'camera_url' in new_values.keys() and \
2724
                new_values['camera_url'] is not None and \
2725
                len(str(new_values['camera_url'])) > 0:
2726
            camera_url = str.strip(new_values['camera_url'])
2727
        else:
2728
            camera_url = None
2729
2730
        if 'description' in new_values.keys() and \
2731
                new_values['description'] is not None and \
2732
                len(str(new_values['description'])) > 0:
2733
            description = str.strip(new_values['description'])
2734
        else:
2735
            description = None
2736
2737
        cnx = mysql.connector.connect(**config.myems_system_db)
2738
        cursor = cnx.cursor()
2739
2740
        cursor.execute(" SELECT name "
2741
                       " FROM tbl_equipments "
2742
                       " WHERE name = %s ", (name,))
2743
        if cursor.fetchone() is not None:
2744
            cursor.close()
2745
            cnx.close()
2746
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
2747
                                   description='API.EQUIPMENT_NAME_IS_ALREADY_IN_USE')
2748
2749
        if cost_center_id is not None:
2750
            cursor.execute(" SELECT name "
2751
                           " FROM tbl_cost_centers "
2752
                           " WHERE id = %s ",
2753
                           (new_values['cost_center']['id'],))
2754
            row = cursor.fetchone()
2755
            if row is None:
2756
                cursor.close()
2757
                cnx.close()
2758
                raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
2759
                                       description='API.COST_CENTER_NOT_FOUND')
2760
        if svg_id is not None:
2761
            cursor.execute(" SELECT name "
2762
                           " FROM tbl_svgs "
2763
                           " WHERE id = %s ",
2764
                           (svg_id,))
2765
            row = cursor.fetchone()
2766
            if row is None:
2767
                cursor.close()
2768
                cnx.close()
2769
                raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
2770
                                       description='API.SVG_NOT_FOUND')
2771
2772
        add_values = (" INSERT INTO tbl_equipments "
2773
                      "    (name, uuid, is_input_counted, is_output_counted, "
2774
                      "     cost_center_id, svg_id, camera_url, description) "
2775
                      " VALUES (%s, %s, %s, %s, %s, %s, %s, %s) ")
2776
        cursor.execute(add_values, (name,
2777
                                    str(uuid.uuid4()),
2778
                                    is_input_counted,
2779
                                    is_output_counted,
2780
                                    cost_center_id,
2781
                                    svg_id,
2782
                                    camera_url,
2783
                                    description))
2784
        new_id = cursor.lastrowid
2785
        if new_values['commands'] is not None and len(new_values['commands']) > 0:
2786
            for command in new_values['commands']:
2787
                cursor.execute(" SELECT name "
2788
                               " FROM tbl_commands "
2789
                               " WHERE id = %s ", (command['id'],))
2790
                if cursor.fetchone() is None:
2791
                    cursor.close()
2792
                    cnx.close()
2793
                    raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
2794
                                           description='API.COMMAND_NOT_FOUND')
2795
2796
                query = (" SELECT id "
2797
                         " FROM tbl_equipments_commands "
2798
                         " WHERE equipment_id = %s AND command_id = %s")
2799
                cursor.execute(query, (new_id, command['id'],))
2800
                if cursor.fetchone() is not None:
2801
                    cursor.close()
2802
                    cnx.close()
2803
                    raise falcon.HTTPError(status=falcon.HTTP_400, title='API.ERROR',
2804
                                           description='API.EQUIPMENT_COMMAND_RELATION_EXISTS')
2805
2806
                add_row = (" INSERT INTO tbl_equipments_commands (equipment_id, command_id) "
2807
                           " VALUES (%s, %s) ")
2808
                cursor.execute(add_row, (new_id, command['id'],))
2809
        if new_values['meters'] is not None and len(new_values['meters']) > 0:
2810
            for meter in new_values['meters']:
2811
                cursor.execute(" SELECT name "
2812
                               " FROM tbl_meters "
2813
                               " WHERE id = %s ", (meter['id'],))
2814
                if cursor.fetchone() is None:
2815
                    cursor.close()
2816
                    cnx.close()
2817
                    raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
2818
                                           description='API.METER_NOT_FOUND')
2819
2820
                query = (" SELECT id "
2821
                         " FROM tbl_equipments_meters "
2822
                         " WHERE equipment_id = %s AND meter_id = %s")
2823
                cursor.execute(query, (new_id, meter['id'],))
2824
                if cursor.fetchone() is not None:
2825
                    cursor.close()
2826
                    cnx.close()
2827
                    raise falcon.HTTPError(status=falcon.HTTP_400, title='API.ERROR',
2828
                                           description='API.EQUIPMENT_METER_RELATION_EXISTS')
2829
2830
                add_row = (" INSERT INTO tbl_equipments_meters (equipment_id, meter_id, is_output ) "
2831
                           " VALUES (%s, %s, %s) ")
2832
                cursor.execute(add_row, (new_id, meter['id'], meter['is_output']))
2833
        if new_values['offline_meters'] is not None and len(new_values['offline_meters']) > 0:
2834
            for offline_meter in new_values['offline_meters']:
2835
                cursor.execute(" SELECT name "
2836
                               " FROM tbl_offline_meters "
2837
                               " WHERE id = %s ", (offline_meter['id'],))
2838
                if cursor.fetchone() is None:
2839
                    cursor.close()
2840
                    cnx.close()
2841
                    raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
2842
                                           description='API.OFFLINE_METER_NOT_FOUND')
2843
2844
                query = (" SELECT id "
2845
                         " FROM tbl_equipments_offline_meters "
2846
                         " WHERE equipment_id = %s AND offline_meter_id = %s")
2847
                cursor.execute(query, (new_id, offline_meter['id'],))
2848
                if cursor.fetchone() is not None:
2849
                    cursor.close()
2850
                    cnx.close()
2851
                    raise falcon.HTTPError(status=falcon.HTTP_400, title='API.ERROR',
2852
                                           description='API.EQUIPMENT_OFFLINE_METER_RELATION_EXISTS')
2853
2854
                add_row = (" INSERT INTO tbl_equipments_offline_meters (equipment_id, offline_meter_id, is_output ) "
2855
                           " VALUES (%s, %s, %s) ")
2856
                cursor.execute(add_row, (new_id, offline_meter['id'], offline_meter['is_output']))
2857
        if new_values['virtual_meters'] is not None and len(new_values['virtual_meters']) > 0:
2858
            for virtual_meter in new_values['virtual_meters']:
2859
                cursor.execute(" SELECT name "
2860
                               " FROM tbl_virtual_meters "
2861
                               " WHERE id = %s ", (virtual_meter['id'],))
2862
                if cursor.fetchone() is None:
2863
                    cursor.close()
2864
                    cnx.close()
2865
                    raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
2866
                                           description='API.VIRTUAL_METER_NOT_FOUND')
2867
2868
                query = (" SELECT id "
2869
                         " FROM tbl_equipments_virtual_meters "
2870
                         " WHERE equipment_id = %s AND virtual_meter_id = %s")
2871
                cursor.execute(query, (new_id, virtual_meter['id'],))
2872
                if cursor.fetchone() is not None:
2873
                    cursor.close()
2874
                    cnx.close()
2875
                    raise falcon.HTTPError(status=falcon.HTTP_400, title='API.ERROR',
2876
                                           description='API.EQUIPMENT_VIRTUAL_METER_RELATION_EXISTS')
2877
2878
                add_row = (" INSERT INTO tbl_equipments_virtual_meters (equipment_id, virtual_meter_id, is_output ) "
2879
                           " VALUES (%s, %s, %s) ")
2880
                cursor.execute(add_row, (new_id, virtual_meter['id'], virtual_meter['is_output']))
2881
        if new_values['parameters'] is not None and len(new_values['parameters']) > 0:
2882
            for parameters in new_values['parameters']:
2883
                cursor.execute(" SELECT name "
2884
                               " FROM tbl_equipments_parameters "
2885
                               " WHERE name = %s AND equipment_id = %s ", (parameters['name'], new_id))
2886
                if cursor.fetchone() is not None:
2887
                    cursor.close()
2888
                    cnx.close()
2889
                    raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
2890
                                           description='API.EQUIPMENT_PARAMETER_NAME_IS_ALREADY_IN_USE')
2891
                if 'point' in parameters:
2892
                    if parameters['point'] is None:
2893
                        point_id = None
2894
                    elif parameters['point']['id'] is not None and \
2895
                            parameters['point']['id'] <= 0:
2896
                        raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
2897
                                               description='API.INVALID_POINT_ID')
2898
                    else:
2899
                        point_id = parameters['point']['id']
2900
                else:
2901
                    point_id = None
2902
                numerator_meter_uuid = None
2903
                if 'numerator_meter' in parameters:
2904
                    if parameters['numerator_meter'] is not None and \
2905
                            isinstance(parameters['numerator_meter']['uuid'], str) and \
2906
                            len(str.strip(parameters['numerator_meter']['uuid'])) > 0:
2907
                        numerator_meter_uuid = str.strip(parameters['numerator_meter']['uuid'])
2908
2909
                denominator_meter_uuid = None
2910
                if 'denominator_meter' in parameters:
2911
                    if parameters['denominator_meter'] is not None and \
2912
                            isinstance(parameters['denominator_meter']['uuid'], str) and \
2913
                            len(str.strip(parameters['denominator_meter']['uuid'])) > 0:
2914
                        denominator_meter_uuid = str.strip(parameters['denominator_meter']['uuid'])
2915
2916
                # validate by parameter type
2917
                if parameters['parameter_type'] == 'point':
2918
                    if point_id is None:
2919
                        raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
2920
                                               description='API.INVALID_POINT_ID')
2921
                    query = (" SELECT id, name "
2922
                             " FROM tbl_points "
2923
                             " WHERE id = %s ")
2924
                    cursor.execute(query, (point_id,))
2925
                    if cursor.fetchone() is None:
2926
                        cursor.close()
2927
                        cnx.close()
2928
                        raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
2929
                                               description='API.POINT_NOT_FOUND')
2930
2931
                elif parameters['parameter_type'] == 'constant':
2932
                    if parameters['constant'] is None:
2933
                        raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
2934
                                               description='API.INVALID_CONSTANT_VALUE')
2935
2936
                elif parameters['parameter_type'] == 'fraction':
2937
                    query = (" SELECT id, name, uuid "
2938
                             " FROM tbl_meters ")
2939
                    cursor.execute(query)
2940
                    rows_meters = cursor.fetchall()
2941
                    meter_dict = dict()
2942
                    if rows_meters is not None and len(rows_meters) > 0:
2943
                        for row in rows_meters:
2944
                            meter_dict[row[2]] = {"type": 'meter',
2945
                                                  "id": row[0],
2946
                                                  "name": row[1],
2947
                                                  "uuid": row[2]}
2948
2949
                    query = (" SELECT id, name, uuid "
2950
                             " FROM tbl_offline_meters ")
2951
                    cursor.execute(query)
2952
                    rows_offline_meters = cursor.fetchall()
2953
2954
                    offline_meter_dict = dict()
2955
                    if rows_offline_meters is not None and len(rows_offline_meters) > 0:
2956
                        for row in rows_offline_meters:
2957
                            offline_meter_dict[row[2]] = {"type": 'offline_meter',
2958
                                                          "id": row[0],
2959
                                                          "name": row[1],
2960
                                                          "uuid": row[2]}
2961
2962
                    query = (" SELECT id, name, uuid "
2963
                             " FROM tbl_virtual_meters ")
2964
                    cursor.execute(query)
2965
                    rows_virtual_meters = cursor.fetchall()
2966
2967
                    virtual_meter_dict = dict()
2968
                    if rows_virtual_meters is not None and len(rows_virtual_meters) > 0:
2969
                        for row in rows_virtual_meters:
2970
                            virtual_meter_dict[row[2]] = {"type": 'virtual_meter',
2971
                                                          "id": row[0],
2972
                                                          "name": row[1],
2973
                                                          "uuid": row[2]}
2974
2975
                    # validate numerator meter uuid
2976
                    if numerator_meter_uuid is None:
2977
                        raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
2978
                                               description='API.INVALID_NUMERATOR_METER_UUID')
2979
2980
                    if meter_dict.get(numerator_meter_uuid) is None and \
2981
                            virtual_meter_dict.get(numerator_meter_uuid) is None and \
2982
                            offline_meter_dict.get(numerator_meter_uuid) is None:
2983
                        raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
2984
                                               description='API.INVALID_NUMERATOR_METER_UUID')
2985
2986
                    # validate denominator meter uuid
2987
                    if denominator_meter_uuid is None:
2988
                        raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
2989
                                               description='API.INVALID_DENOMINATOR_METER_UUID')
2990
2991
                    if denominator_meter_uuid == numerator_meter_uuid:
2992
                        raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
2993
                                               description='API.INVALID_DENOMINATOR_METER_UUID')
2994
2995
                    if denominator_meter_uuid not in meter_dict and \
2996
                            denominator_meter_uuid not in virtual_meter_dict and \
2997
                            denominator_meter_uuid not in offline_meter_dict:
2998
                        raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
2999
                                               description='API.INVALID_DENOMINATOR_METER_UUID')
3000
3001
                add_values = (" INSERT INTO tbl_equipments_parameters "
3002
                              "    (equipment_id, name, parameter_type, constant, "
3003
                              "     point_id, numerator_meter_uuid, denominator_meter_uuid) "
3004
                              " VALUES (%s, %s, %s, %s, %s, %s, %s) ")
3005
                cursor.execute(add_values, (new_id,
3006
                                            parameters['name'],
3007
                                            parameters['parameter_type'],
3008
                                            parameters['constant'],
3009
                                            point_id,
3010
                                            numerator_meter_uuid,
3011
                                            denominator_meter_uuid))
3012
        cnx.commit()
3013
        cursor.close()
3014
        cnx.close()
3015
3016
        # Clear cache after importing equipment
3017
        clear_equipment_cache()
3018
3019
        resp.status = falcon.HTTP_201
3020
        resp.location = '/equipments/' + str(new_id)
3021
3022
3023
class EquipmentClone:
3024
    def __init__(self):
3025
        pass
3026
3027
    @staticmethod
3028
    def on_options(req, resp, id_):
3029
        _ = req
3030
        resp.status = falcon.HTTP_200
3031
        _ = id_
3032
3033
    @staticmethod
3034
    @user_logger
3035
    def on_post(req, resp, id_):
3036
        admin_control(req)
3037
        if not id_.isdigit() or int(id_) <= 0:
3038
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
3039
                                   description='API.INVALID_EQUIPMENT_ID')
3040
3041
        cnx = mysql.connector.connect(**config.myems_system_db)
3042
        cursor = cnx.cursor()
3043
3044
        query = (" SELECT id, name, uuid "
3045
                 " FROM tbl_cost_centers ")
3046
        cursor.execute(query)
3047
        rows_cost_centers = cursor.fetchall()
3048
3049
        cost_center_dict = dict()
3050
        if rows_cost_centers is not None and len(rows_cost_centers) > 0:
3051
            for row in rows_cost_centers:
3052
                cost_center_dict[row[0]] = {"id": row[0],
3053
                                            "name": row[1],
3054
                                            "uuid": row[2]}
3055
3056
        query = (" SELECT id, name, uuid, "
3057
                 "        is_input_counted, is_output_counted, "
3058
                 "        cost_center_id, svg_id, camera_url, description "
3059
                 " FROM tbl_equipments "
3060
                 " WHERE id = %s ")
3061
        cursor.execute(query, (id_,))
3062
        row = cursor.fetchone()
3063
3064
        if row is None:
3065
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
3066
                                   description='API.EQUIPMENT_NOT_FOUND')
3067
        else:
3068
            meta_result = {"id": row[0],
3069
                           "name": row[1],
3070
                           "uuid": row[2],
3071
                           "is_input_counted": bool(row[3]),
3072
                           "is_output_counted": bool(row[4]),
3073
                           "cost_center": cost_center_dict.get(row[5], None),
3074
                           "svg_id": row[6],
3075
                           "camera_url": row[7],
3076
                           "description": row[8],
3077
                           "commands": None,
3078
                           "meters": None,
3079
                           "offline_meters": None,
3080
                           "virtual_meters": None,
3081
                           "parameters": None
3082
                           }
3083
            query = (" SELECT c.id, c.name, c.uuid "
3084
                     " FROM tbl_equipments e, tbl_equipments_commands ec, tbl_commands c "
3085
                     " WHERE ec.equipment_id = e.id AND c.id = ec.command_id AND e.id = %s "
3086
                     " ORDER BY c.id ")
3087
            cursor.execute(query, (id_,))
3088
            rows = cursor.fetchall()
3089
3090
            command_result = list()
3091
            if rows is not None and len(rows) > 0:
3092
                for row in rows:
3093
                    result = {"id": row[0],
3094
                              "name": row[1],
3095
                              "uuid": row[2]}
3096
                    command_result.append(result)
3097
                meta_result['commands'] = command_result
3098
3099
            query = (" SELECT id, name, uuid "
3100
                     " FROM tbl_energy_categories ")
3101
            cursor.execute(query)
3102
            rows_energy_categories = cursor.fetchall()
3103
3104
            energy_category_dict = dict()
3105
            if rows_energy_categories is not None and len(rows_energy_categories) > 0:
3106
                for row in rows_energy_categories:
3107
                    energy_category_dict[row[0]] = {"id": row[0],
3108
                                                    "name": row[1],
3109
                                                    "uuid": row[2]}
3110
3111
            query = (" SELECT m.id, m.name, m.uuid, m.energy_category_id, em.is_output "
3112
                     " FROM tbl_equipments e, tbl_equipments_meters em, tbl_meters m "
3113
                     " WHERE em.equipment_id = e.id AND m.id = em.meter_id AND e.id = %s "
3114
                     " ORDER BY m.id ")
3115
            cursor.execute(query, (id_,))
3116
            rows = cursor.fetchall()
3117
3118
            meter_result = list()
3119
            if rows is not None and len(rows) > 0:
3120
                for row in rows:
3121
                    result = {"id": row[0],
3122
                              "name": row[1],
3123
                              "uuid": row[2],
3124
                              "energy_category": energy_category_dict.get(row[3], None),
3125
                              "is_output": bool(row[4])}
3126
                    meter_result.append(result)
3127
                meta_result['meters'] = meter_result
3128
            query = (" SELECT m.id, m.name, m.uuid, m.energy_category_id, em.is_output "
3129
                     " FROM tbl_equipments e, tbl_equipments_offline_meters em, tbl_offline_meters m "
3130
                     " WHERE em.equipment_id = e.id AND m.id = em.offline_meter_id AND e.id = %s "
3131
                     " ORDER BY m.id ")
3132
            cursor.execute(query, (id_,))
3133
            rows = cursor.fetchall()
3134
3135
            offlinemeter_result = list()
3136
            if rows is not None and len(rows) > 0:
3137
                for row in rows:
3138
                    result = {"id": row[0],
3139
                              "name": row[1],
3140
                              "uuid": row[2],
3141
                              "energy_category": energy_category_dict.get(row[3], None),
3142
                              "is_output": bool(row[4])}
3143
                    offlinemeter_result.append(result)
3144
                meta_result['offline_meters'] = offlinemeter_result
3145
            query = (" SELECT m.id, m.name, m.uuid, m.energy_category_id, em.is_output "
3146
                     " FROM tbl_equipments e, tbl_equipments_virtual_meters em, tbl_virtual_meters m "
3147
                     " WHERE em.equipment_id = e.id AND m.id = em.virtual_meter_id AND e.id = %s "
3148
                     " ORDER BY m.id ")
3149
            cursor.execute(query, (id_,))
3150
            rows = cursor.fetchall()
3151
3152
            virtualmeter_result = list()
3153
            if rows is not None and len(rows) > 0:
3154
                for row in rows:
3155
                    result = {"id": row[0],
3156
                              "name": row[1],
3157
                              "uuid": row[2],
3158
                              "energy_category": energy_category_dict.get(row[3], None),
3159
                              "is_output": bool(row[4])}
3160
                    virtualmeter_result.append(result)
3161
                meta_result['virtual_meters'] = virtualmeter_result
3162
            query = (" SELECT id, name "
3163
                     " FROM tbl_points ")
3164
            cursor.execute(query)
3165
            rows_points = cursor.fetchall()
3166
3167
            point_dict = dict()
3168
            if rows_points is not None and len(rows_points) > 0:
3169
                for row in rows_points:
3170
                    point_dict[row[0]] = {"id": row[0],
3171
                                          "name": row[1]}
3172
3173
            query = (" SELECT id, name, uuid "
3174
                     " FROM tbl_meters ")
3175
            cursor.execute(query)
3176
            rows_meters = cursor.fetchall()
3177
3178
            meter_dict = dict()
3179
            if rows_meters is not None and len(rows_meters) > 0:
3180
                for row in rows_meters:
3181
                    meter_dict[row[2]] = {"type": 'meter',
3182
                                          "id": row[0],
3183
                                          "name": row[1],
3184
                                          "uuid": row[2]}
3185
3186
            query = (" SELECT id, name, uuid "
3187
                     " FROM tbl_offline_meters ")
3188
            cursor.execute(query)
3189
            rows_offline_meters = cursor.fetchall()
3190
3191
            offline_meter_dict = dict()
3192
            if rows_offline_meters is not None and len(rows_offline_meters) > 0:
3193
                for row in rows_offline_meters:
3194
                    offline_meter_dict[row[2]] = {"type": 'offline_meter',
3195
                                                  "id": row[0],
3196
                                                  "name": row[1],
3197
                                                  "uuid": row[2]}
3198
3199
            query = (" SELECT id, name, uuid "
3200
                     " FROM tbl_virtual_meters ")
3201
            cursor.execute(query)
3202
            rows_virtual_meters = cursor.fetchall()
3203
3204
            virtual_meter_dict = dict()
3205
            if rows_virtual_meters is not None and len(rows_virtual_meters) > 0:
3206
                for row in rows_virtual_meters:
3207
                    virtual_meter_dict[row[2]] = {"type": 'virtual_meter',
3208
                                                  "id": row[0],
3209
                                                  "name": row[1],
3210
                                                  "uuid": row[2]}
3211
3212
            query = (" SELECT id, name, parameter_type, "
3213
                     "        constant, point_id, numerator_meter_uuid, denominator_meter_uuid "
3214
                     " FROM tbl_equipments_parameters "
3215
                     " WHERE equipment_id = %s "
3216
                     " ORDER BY id ")
3217
            cursor.execute(query, (id_,))
3218
            rows_parameters = cursor.fetchall()
3219
3220
            parameters_result = list()
3221 View Code Duplication
            if rows_parameters is not None and len(rows_parameters) > 0:
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
3222
                for row in rows_parameters:
3223
                    constant = None
3224
                    point = None
3225
                    numerator_meter = None
3226
                    denominator_meter = None
3227
                    if row[2] == 'point':
3228
                        point = point_dict.get(row[4], None)
3229
                        constant = None
3230
                        numerator_meter = None
3231
                        denominator_meter = None
3232
                    elif row[2] == 'constant':
3233
                        constant = row[3]
3234
                        point = None
3235
                        numerator_meter = None
3236
                        denominator_meter = None
3237
                    elif row[2] == 'fraction':
3238
                        constant = None
3239
                        point = None
3240
                        # find numerator meter by uuid
3241
                        numerator_meter = meter_dict.get(row[5], None)
3242
                        if numerator_meter is None:
3243
                            numerator_meter = virtual_meter_dict.get(row[5], None)
3244
                        if numerator_meter is None:
3245
                            numerator_meter = offline_meter_dict.get(row[5], None)
3246
                        # find denominator meter by uuid
3247
                        denominator_meter = meter_dict.get(row[6], None)
3248
                        if denominator_meter is None:
3249
                            denominator_meter = virtual_meter_dict.get(row[6], None)
3250
                        if denominator_meter is None:
3251
                            denominator_meter = offline_meter_dict.get(row[6], None)
3252
3253
                    result = {"id": row[0],
3254
                              "name": row[1],
3255
                              "parameter_type": row[2],
3256
                              "constant": constant,
3257
                              "point": point,
3258
                              "numerator_meter": numerator_meter,
3259
                              "denominator_meter": denominator_meter}
3260
                    parameters_result.append(result)
3261
                meta_result['parameters'] = parameters_result
3262
            timezone_offset = int(config.utc_offset[1:3]) * 60 + int(config.utc_offset[4:6])
3263
            if config.utc_offset[0] == '-':
3264
                timezone_offset = -timezone_offset
3265
            new_name = (str.strip(meta_result['name']) +
3266
                        (datetime.utcnow() + timedelta(minutes=timezone_offset)).isoformat(sep='-', timespec='seconds'))
3267
            add_values = (" INSERT INTO tbl_equipments "
3268
                          "    (name, uuid, is_input_counted, is_output_counted, "
3269
                          "     cost_center_id, svg_id, camera_url, description) "
3270
                          " VALUES (%s, %s, %s, %s, %s, %s, %s, %s) ")
3271
            cursor.execute(add_values, (new_name,
3272
                                        str(uuid.uuid4()),
3273
                                        meta_result['is_input_counted'],
3274
                                        meta_result['is_output_counted'],
3275
                                        meta_result['cost_center']['id'],
3276
                                        meta_result['svg_id'],
3277
                                        meta_result['camera_url'],
3278
                                        meta_result['description']))
3279
            new_id = cursor.lastrowid
3280
            if meta_result['commands'] is not None and len(meta_result['commands']) > 0:
3281
                for command in meta_result['commands']:
3282
                    cursor.execute(" SELECT name "
3283
                                   " FROM tbl_commands "
3284
                                   " WHERE id = %s ", (command['id'],))
3285
                    if cursor.fetchone() is None:
3286
                        cursor.close()
3287
                        cnx.close()
3288
                        raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
3289
                                               description='API.COMMAND_NOT_FOUND')
3290
3291
                    query = (" SELECT id "
3292
                             " FROM tbl_equipments_commands "
3293
                             " WHERE equipment_id = %s AND command_id = %s")
3294
                    cursor.execute(query, (new_id, command['id'],))
3295
                    if cursor.fetchone() is not None:
3296
                        cursor.close()
3297
                        cnx.close()
3298
                        raise falcon.HTTPError(status=falcon.HTTP_400, title='API.ERROR',
3299
                                               description='API.EQUIPMENT_COMMAND_RELATION_EXISTS')
3300
3301
                    add_row = (" INSERT INTO tbl_equipments_commands (equipment_id, command_id) "
3302
                               " VALUES (%s, %s) ")
3303
                    cursor.execute(add_row, (new_id, command['id'],))
3304
            if meta_result['meters'] is not None and len(meta_result['meters']) > 0:
3305
                for meter in meta_result['meters']:
3306
                    cursor.execute(" SELECT name "
3307
                                   " FROM tbl_meters "
3308
                                   " WHERE id = %s ", (meter['id'],))
3309
                    if cursor.fetchone() is None:
3310
                        cursor.close()
3311
                        cnx.close()
3312
                        raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
3313
                                               description='API.METER_NOT_FOUND')
3314
3315
                    query = (" SELECT id "
3316
                             " FROM tbl_equipments_meters "
3317
                             " WHERE equipment_id = %s AND meter_id = %s")
3318
                    cursor.execute(query, (new_id, meter['id'],))
3319
                    if cursor.fetchone() is not None:
3320
                        cursor.close()
3321
                        cnx.close()
3322
                        raise falcon.HTTPError(status=falcon.HTTP_400, title='API.ERROR',
3323
                                               description='API.EQUIPMENT_METER_RELATION_EXISTS')
3324
3325
                    add_row = (" INSERT INTO tbl_equipments_meters (equipment_id, meter_id, is_output ) "
3326
                               " VALUES (%s, %s, %s) ")
3327
                    cursor.execute(add_row, (new_id, meter['id'], meter['is_output']))
3328
            if meta_result['offline_meters'] is not None and len(meta_result['offline_meters']) > 0:
3329
                for offline_meter in meta_result['offline_meters']:
3330
                    cursor.execute(" SELECT name "
3331
                                   " FROM tbl_offline_meters "
3332
                                   " WHERE id = %s ", (offline_meter['id'],))
3333
                    if cursor.fetchone() is None:
3334
                        cursor.close()
3335
                        cnx.close()
3336
                        raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
3337
                                               description='API.OFFLINE_METER_NOT_FOUND')
3338
3339
                    query = (" SELECT id "
3340
                             " FROM tbl_equipments_offline_meters "
3341
                             " WHERE equipment_id = %s AND offline_meter_id = %s")
3342
                    cursor.execute(query, (new_id, offline_meter['id'],))
3343
                    if cursor.fetchone() is not None:
3344
                        cursor.close()
3345
                        cnx.close()
3346
                        raise falcon.HTTPError(status=falcon.HTTP_400, title='API.ERROR',
3347
                                               description='API.EQUIPMENT_OFFLINE_METER_RELATION_EXISTS')
3348
3349
                    add_row = (
3350
                        " INSERT INTO tbl_equipments_offline_meters (equipment_id, offline_meter_id, is_output ) "
3351
                        " VALUES (%s, %s, %s) ")
3352
                    cursor.execute(add_row, (new_id, offline_meter['id'], offline_meter['is_output']))
3353
            if meta_result['virtual_meters'] is not None and len(meta_result['virtual_meters']) > 0:
3354
                for virtual_meter in meta_result['virtual_meters']:
3355
                    cursor.execute(" SELECT name "
3356
                                   " FROM tbl_virtual_meters "
3357
                                   " WHERE id = %s ", (virtual_meter['id'],))
3358
                    if cursor.fetchone() is None:
3359
                        cursor.close()
3360
                        cnx.close()
3361
                        raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
3362
                                               description='API.VIRTUAL_METER_NOT_FOUND')
3363
3364
                    query = (" SELECT id "
3365
                             " FROM tbl_equipments_virtual_meters "
3366
                             " WHERE equipment_id = %s AND virtual_meter_id = %s")
3367
                    cursor.execute(query, (new_id, virtual_meter['id'],))
3368
                    if cursor.fetchone() is not None:
3369
                        cursor.close()
3370
                        cnx.close()
3371
                        raise falcon.HTTPError(status=falcon.HTTP_400, title='API.ERROR',
3372
                                               description='API.EQUIPMENT_VIRTUAL_METER_RELATION_EXISTS')
3373
3374
                    add_row = (
3375
                        " INSERT INTO tbl_equipments_virtual_meters (equipment_id, virtual_meter_id, is_output ) "
3376
                        " VALUES (%s, %s, %s) ")
3377
                    cursor.execute(add_row, (new_id, virtual_meter['id'], virtual_meter['is_output']))
3378 View Code Duplication
            if meta_result['parameters'] is not None and len(meta_result['parameters']) > 0:
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
3379
                for parameters in meta_result['parameters']:
3380
                    cursor.execute(" SELECT name "
3381
                                   " FROM tbl_equipments_parameters "
3382
                                   " WHERE name = %s AND equipment_id = %s ", (parameters['name'], new_id))
3383
                    if cursor.fetchone() is not None:
3384
                        cursor.close()
3385
                        cnx.close()
3386
                        raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
3387
                                               description='API.EQUIPMENT_PARAMETER_NAME_IS_ALREADY_IN_USE')
3388
                    if 'point' in parameters:
3389
                        if parameters['point'] is None:
3390
                            point_id = None
3391
                        elif parameters['point']['id'] is not None and \
3392
                                parameters['point']['id'] <= 0:
3393
                            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
3394
                                                   description='API.INVALID_POINT_ID')
3395
                        else:
3396
                            point_id = parameters['point']['id']
3397
                    else:
3398
                        point_id = None
3399
                    numerator_meter_uuid = None
3400
                    if 'numerator_meter' in parameters:
3401
                        if parameters['numerator_meter'] is not None and \
3402
                                isinstance(parameters['numerator_meter']['uuid'], str) and \
3403
                                len(str.strip(parameters['numerator_meter']['uuid'])) > 0:
3404
                            numerator_meter_uuid = str.strip(parameters['numerator_meter']['uuid'])
3405
3406
                    denominator_meter_uuid = None
3407
                    if 'denominator_meter' in parameters:
3408
                        if parameters['denominator_meter'] is not None and \
3409
                                isinstance(parameters['denominator_meter']['uuid'], str) and \
3410
                                len(str.strip(parameters['denominator_meter']['uuid'])) > 0:
3411
                            denominator_meter_uuid = str.strip(parameters['denominator_meter']['uuid'])
3412
3413
                    # validate by parameter type
3414
                    if parameters['parameter_type'] == 'point':
3415
                        if point_id is None:
3416
                            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
3417
                                                   description='API.INVALID_POINT_ID')
3418
                        query = (" SELECT id, name "
3419
                                 " FROM tbl_points "
3420
                                 " WHERE id = %s ")
3421
                        cursor.execute(query, (point_id,))
3422
                        if cursor.fetchone() is None:
3423
                            cursor.close()
3424
                            cnx.close()
3425
                            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
3426
                                                   description='API.POINT_NOT_FOUND')
3427
3428
                    elif parameters['parameter_type'] == 'constant':
3429
                        if parameters['constant'] is None:
3430
                            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
3431
                                                   description='API.INVALID_CONSTANT_VALUE')
3432
3433
                    elif parameters['parameter_type'] == 'fraction':
3434
                        query = (" SELECT id, name, uuid "
3435
                                 " FROM tbl_meters ")
3436
                        cursor.execute(query)
3437
                        rows_meters = cursor.fetchall()
3438
                        meter_dict = dict()
3439
                        if rows_meters is not None and len(rows_meters) > 0:
3440
                            for row in rows_meters:
3441
                                meter_dict[row[2]] = {"type": 'meter',
3442
                                                      "id": row[0],
3443
                                                      "name": row[1],
3444
                                                      "uuid": row[2]}
3445
3446
                        query = (" SELECT id, name, uuid "
3447
                                 " FROM tbl_offline_meters ")
3448
                        cursor.execute(query)
3449
                        rows_offline_meters = cursor.fetchall()
3450
3451
                        offline_meter_dict = dict()
3452
                        if rows_offline_meters is not None and len(rows_offline_meters) > 0:
3453
                            for row in rows_offline_meters:
3454
                                offline_meter_dict[row[2]] = {"type": 'offline_meter',
3455
                                                              "id": row[0],
3456
                                                              "name": row[1],
3457
                                                              "uuid": row[2]}
3458
3459
                        query = (" SELECT id, name, uuid "
3460
                                 " FROM tbl_virtual_meters ")
3461
                        cursor.execute(query)
3462
                        rows_virtual_meters = cursor.fetchall()
3463
3464
                        virtual_meter_dict = dict()
3465
                        if rows_virtual_meters is not None and len(rows_virtual_meters) > 0:
3466
                            for row in rows_virtual_meters:
3467
                                virtual_meter_dict[row[2]] = {"type": 'virtual_meter',
3468
                                                              "id": row[0],
3469
                                                              "name": row[1],
3470
                                                              "uuid": row[2]}
3471
3472
                        # validate numerator meter uuid
3473
                        if numerator_meter_uuid is None:
3474
                            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
3475
                                                   description='API.INVALID_NUMERATOR_METER_UUID')
3476
3477
                        if meter_dict.get(numerator_meter_uuid) is None and \
3478
                                virtual_meter_dict.get(numerator_meter_uuid) is None and \
3479
                                offline_meter_dict.get(numerator_meter_uuid) is None:
3480
                            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
3481
                                                   description='API.INVALID_NUMERATOR_METER_UUID')
3482
3483
                        # validate denominator meter uuid
3484
                        if denominator_meter_uuid == numerator_meter_uuid:
3485
                            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
3486
                                                   description='API.INVALID_DENOMINATOR_METER_UUID')
3487
3488
                        if denominator_meter_uuid not in meter_dict and \
3489
                                denominator_meter_uuid not in virtual_meter_dict and \
3490
                                denominator_meter_uuid not in offline_meter_dict:
3491
                            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
3492
                                                   description='API.INVALID_DENOMINATOR_METER_UUID')
3493
3494
                    add_values = (" INSERT INTO tbl_equipments_parameters "
3495
                                  "    (equipment_id, name, parameter_type, constant, "
3496
                                  "     point_id, numerator_meter_uuid, denominator_meter_uuid) "
3497
                                  " VALUES (%s, %s, %s, %s, %s, %s, %s) ")
3498
                    cursor.execute(add_values, (new_id,
3499
                                                parameters['name'],
3500
                                                parameters['parameter_type'],
3501
                                                parameters['constant'],
3502
                                                point_id,
3503
                                                numerator_meter_uuid,
3504
                                                denominator_meter_uuid))
3505
            cnx.commit()
3506
            cursor.close()
3507
            cnx.close()
3508
3509
            # Clear cache after cloning equipment
3510
            clear_equipment_cache()
3511
3512
            resp.status = falcon.HTTP_201
3513
            resp.location = '/equipments/' + str(new_id)
3514
3515 View Code Duplication
class EquipmentDataSourceCollection:
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
3516
    def __init__(self):
3517
        pass
3518
3519
    @staticmethod
3520
    def on_options(req, resp, id_):
3521
        _ = req
3522
        _ = id_
3523
        resp.status = falcon.HTTP_200
3524
3525
    @staticmethod
3526
    def on_get(req, resp, id_):
3527
        if 'API-KEY' not in req.headers or \
3528
                not isinstance(req.headers['API-KEY'], str) or \
3529
                len(str.strip(req.headers['API-KEY'])) == 0:
3530
            access_control(req)
3531
        else:
3532
            api_key_control(req)
3533
3534
        if not id_.isdigit() or int(id_) <= 0:
3535
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
3536
                                   description='API.INVALID_EQUIPMENT_ID')
3537
3538
        cnx = mysql.connector.connect(**config.myems_system_db)
3539
        cursor = cnx.cursor()
3540
3541
        cursor.execute(" SELECT name FROM tbl_equipments WHERE id = %s ", (id_,))
3542
        if cursor.fetchone() is None:
3543
            cursor.close()
3544
            cnx.close()
3545
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
3546
                                   description='API.EQUIPMENT_NOT_FOUND')
3547
3548
        query = (" SELECT ds.id, ds.name, ds.uuid "
3549
                 " FROM tbl_equipments e, tbl_equipments_data_sources eds, tbl_data_sources ds "
3550
                 " WHERE eds.equipment_id = e.id AND ds.id = eds.data_source_id AND e.id = %s "
3551
                 " ORDER BY ds.id ")
3552
        cursor.execute(query, (id_,))
3553
        rows = cursor.fetchall()
3554
3555
        result = list()
3556
        if rows is not None and len(rows) > 0:
3557
            for row in rows:
3558
                meta_result = {"id": row[0], "name": row[1], "uuid": row[2]}
3559
                result.append(meta_result)
3560
3561
        cursor.close()
3562
        cnx.close()
3563
3564
        resp.text = json.dumps(result)
3565
3566
    @staticmethod
3567
    @user_logger
3568
    def on_post(req, resp, id_):
3569
        admin_control(req)
3570
        try:
3571
            raw_json = req.stream.read().decode('utf-8')
3572
        except UnicodeDecodeError as ex:
3573
            print("Failed to decode request")
3574
            raise falcon.HTTPError(status=falcon.HTTP_400,
3575
                                   title='API.BAD_REQUEST',
3576
                                   description='API.INVALID_ENCODING')
3577
        except Exception as ex:
3578
            print("Unexpected error reading request stream")
3579
            raise falcon.HTTPError(status=falcon.HTTP_400,
3580
                                   title='API.BAD_REQUEST',
3581
                                   description='API.FAILED_TO_READ_REQUEST_STREAM')
3582
        if not id_.isdigit() or int(id_) <= 0:
3583
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
3584
                                   description='API.INVALID_EQUIPMENT_ID')
3585
3586
        new_values = json.loads(raw_json)
3587
3588
        if 'data_source_id' not in new_values['data'].keys() or \
3589
                not isinstance(new_values['data']['data_source_id'], int) or \
3590
                new_values['data']['data_source_id'] <= 0:
3591
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
3592
                                   description='API.INVALID_DATA_SOURCE_ID')
3593
3594
        data_source_id = new_values['data']['data_source_id']
3595
3596
        cnx = mysql.connector.connect(**config.myems_system_db)
3597
        cursor = cnx.cursor()
3598
3599
        cursor.execute(" SELECT name FROM tbl_equipments WHERE id = %s ", (id_,))
3600
        if cursor.fetchone() is None:
3601
            cursor.close()
3602
            cnx.close()
3603
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
3604
                                   description='API.EQUIPMENT_NOT_FOUND')
3605
3606
        cursor.execute(" SELECT name FROM tbl_data_sources WHERE id = %s ", (data_source_id,))
3607
        if cursor.fetchone() is None:
3608
            cursor.close()
3609
            cnx.close()
3610
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
3611
                                   description='API.DATA_SOURCE_NOT_FOUND')
3612
3613
        cursor.execute(" SELECT id "
3614
                       " FROM tbl_equipments_data_sources "
3615
                       " WHERE equipment_id = %s AND data_source_id = %s", (id_, data_source_id))
3616
        if cursor.fetchone() is not None:
3617
            cursor.close()
3618
            cnx.close()
3619
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.ERROR',
3620
                                   description='API.EQUIPMENT_DATA_SOURCE_RELATION_EXISTS')
3621
3622
        cursor.execute(" INSERT INTO tbl_equipments_data_sources (equipment_id, data_source_id) "
3623
                       " VALUES (%s, %s) ", (id_, data_source_id))
3624
        cnx.commit()
3625
        cursor.close()
3626
        cnx.close()
3627
3628
        # Clear cache after adding data source
3629
        clear_equipment_cache(equipment_id=id_)
3630
3631
        resp.status = falcon.HTTP_201
3632
        resp.location = '/equipments/' + str(id_) + '/datasources/' + str(data_source_id)
3633
3634 View Code Duplication
class EquipmentDataSourceItem:
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
3635
    def __init__(self):
3636
        pass
3637
3638
    @staticmethod
3639
    def on_options(req, resp, id_, dsid):
3640
        _ = req
3641
        _ = id_
3642
        _ = dsid
3643
        resp.status = falcon.HTTP_200
3644
3645
    @staticmethod
3646
    @user_logger
3647
    def on_delete(req, resp, id_, dsid):
3648
        admin_control(req)
3649
3650
        if not id_.isdigit() or int(id_) <= 0:
3651
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
3652
                                   description='API.INVALID_EQUIPMENT_ID')
3653
3654
        if not dsid.isdigit() or int(dsid) <= 0:
3655
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
3656
                                   description='API.INVALID_DATA_SOURCE_ID')
3657
3658
        cnx = mysql.connector.connect(**config.myems_system_db)
3659
        cursor = cnx.cursor()
3660
3661
        cursor.execute(" SELECT name FROM tbl_equipments WHERE id = %s ", (id_,))
3662
        if cursor.fetchone() is None:
3663
            cursor.close()
3664
            cnx.close()
3665
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
3666
                                   description='API.EQUIPMENT_NOT_FOUND')
3667
3668
        cursor.execute(" SELECT name FROM tbl_data_sources WHERE id = %s ", (dsid,))
3669
        if cursor.fetchone() is None:
3670
            cursor.close()
3671
            cnx.close()
3672
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
3673
                                   description='API.DATA_SOURCE_NOT_FOUND')
3674
3675
        cursor.execute(" SELECT id "
3676
                       " FROM tbl_equipments_data_sources "
3677
                       " WHERE equipment_id = %s AND data_source_id = %s ", (id_, dsid))
3678
        if cursor.fetchone() is None:
3679
            cursor.close()
3680
            cnx.close()
3681
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
3682
                                   description='API.EQUIPMENT_DATA_SOURCE_RELATION_NOT_FOUND')
3683
3684
        cursor.execute(" DELETE FROM tbl_equipments_data_sources "
3685
                       " WHERE equipment_id = %s AND data_source_id = %s ", (id_, dsid))
3686
        cnx.commit()
3687
        cursor.close()
3688
        cnx.close()
3689
3690
        # Clear cache after deleting data source
3691
        clear_equipment_cache(equipment_id=id_)
3692
3693
        resp.status = falcon.HTTP_204
3694
3695
class EquipmentAddPointsCollection:
3696
    def __init__(self):
3697
        pass
3698
3699
    @staticmethod
3700
    def on_options(req, resp, id_):
3701
        _ = req
3702
        resp.status = falcon.HTTP_200
3703
        _ = id_
3704
3705
    @staticmethod
3706
    def on_get(req, resp, id_):
3707
        if 'API-KEY' not in req.headers or \
3708
                not isinstance(req.headers['API-KEY'], str) or \
3709
                len(str.strip(req.headers['API-KEY'])) == 0:
3710
            access_control(req)
3711
        else:
3712
            api_key_control(req)
3713
        if not id_.isdigit() or int(id_) <= 0:
3714
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
3715
                                   description='API.INVALID_EQUIPMENT_ID')
3716
3717
        cnx = mysql.connector.connect(**config.myems_system_db)
3718
        cursor = cnx.cursor()
3719
3720
        pids = list()
3721
        cursor.execute(" SELECT id "
3722
                       " FROM tbl_points "
3723
                       " WHERE data_source_id in(select data_source_id from tbl_equipments_data_sources where equipment_id = %s) ", (id_,))
3724
        rows = cursor.fetchall()
3725
        if rows is not None and len(rows) > 0:
3726
            for row in rows:
3727
                pids.append(row[0])
3728
3729
        query = (" SELECT id, name, uuid "
3730
                 " FROM tbl_data_sources ")
3731
        cursor.execute(query)
3732
        rows_data_sources = cursor.fetchall()
3733
3734
        data_source_dict = dict()
3735
        if rows_data_sources is not None and len(rows_data_sources) > 0:
3736
            for row in rows_data_sources:
3737
                data_source_dict[row[0]] = {"id": row[0],
3738
                                            "name": row[1],
3739
                                            "uuid": row[2]}
3740
3741
        query = (" SELECT id, name, data_source_id, object_type, units, "
3742
                 "        high_limit, low_limit, higher_limit, lower_limit, ratio, offset_constant, "
3743
                 "        is_trend, is_virtual, address, description, faults, definitions "
3744
                 " FROM tbl_points ")
3745
        cursor.execute(query)
3746
        rows = cursor.fetchall()
3747
        cursor.close()
3748
        cnx.close()
3749
3750
        result = list()
3751 View Code Duplication
        if rows is not None and len(rows) > 0:
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
3752
            for row in rows:
3753
                if row[0] not in pids:
3754
                    continue
3755
                meta_result = {"id": row[0],
3756
                               "name": row[1],
3757
                               "data_source": data_source_dict.get(row[2], None),
3758
                               "object_type": row[3],
3759
                               "units": row[4],
3760
                               "high_limit": row[5],
3761
                               "low_limit": row[6],
3762
                               "higher_limit": row[7],
3763
                               "lower_limit": row[8],
3764
                               "ratio": Decimal(row[9]),
3765
                               "offset_constant": Decimal(row[10]),
3766
                               "is_trend": bool(row[11]),
3767
                               "is_virtual": bool(row[12]),
3768
                               "address": row[13],
3769
                               "description": row[14],
3770
                               "faults": row[15],
3771
                               "definitions": row[16]}
3772
                result.append(meta_result)
3773
        resp.text = json.dumps(result)
3774
3775
class EquipmentEditPointsCollection:
3776
    def __init__(self):
3777
        pass
3778
3779
    @staticmethod
3780
    def on_options(req, resp, id_, pid):
3781
        _ = req
3782
        resp.status = falcon.HTTP_200
3783
        _ = id_
3784
        _ = pid
3785
3786
    @staticmethod
3787
    def on_get(req, resp, id_, pid):
3788
        if 'API-KEY' not in req.headers or \
3789
                not isinstance(req.headers['API-KEY'], str) or \
3790
                len(str.strip(req.headers['API-KEY'])) == 0:
3791
            access_control(req)
3792
        else:
3793
            api_key_control(req)
3794
        if not id_.isdigit() or int(id_) <= 0:
3795
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
3796
                                   description='API.INVALID_EQUIPMENT_ID')
3797
3798
        cnx = mysql.connector.connect(**config.myems_system_db)
3799
        cursor = cnx.cursor()
3800
3801
        equipment_pids = list()
3802
        cursor.execute(" SELECT point_id "
3803
                       " FROM tbl_equipments_parameters "
3804
                       " WHERE id = %s ", (pid,))
3805
        rows = cursor.fetchall()
3806
        if rows is not None and len(rows) > 0:
3807
            for row in rows:
3808
                equipment_pids.append(row[0])
3809
3810
        pids = list()
3811
        cursor.execute(" SELECT id "
3812
                       " FROM tbl_points "
3813
                       " WHERE data_source_id in(select data_source_id from tbl_equipments_data_sources where equipment_id = %s) ", (id_,))
3814
        rows = cursor.fetchall()
3815
        if rows is not None and len(rows) > 0:
3816
            for row in rows:
3817
                pids.append(row[0])
3818
3819
        pids = pids + equipment_pids
3820
        query = (" SELECT id, name, uuid "
3821
                 " FROM tbl_data_sources ")
3822
        cursor.execute(query)
3823
        rows_data_sources = cursor.fetchall()
3824
3825
        data_source_dict = dict()
3826
        if rows_data_sources is not None and len(rows_data_sources) > 0:
3827
            for row in rows_data_sources:
3828
                data_source_dict[row[0]] = {"id": row[0],
3829
                                            "name": row[1],
3830
                                            "uuid": row[2]}
3831
3832
        query = (" SELECT id, name, data_source_id, object_type, units, "
3833
                 "        high_limit, low_limit, higher_limit, lower_limit, ratio, offset_constant, "
3834
                 "        is_trend, is_virtual, address, description, faults, definitions "
3835
                 " FROM tbl_points ")
3836
        cursor.execute(query)
3837
        rows = cursor.fetchall()
3838
        cursor.close()
3839
        cnx.close()
3840
3841
        result_first = list()
3842
        result = list()
3843
        if rows is not None and len(rows) > 0:
3844
            for row in rows:
3845
                if row[0] not in pids:
3846
                    continue
3847
                meta_result = {"id": row[0],
3848
                               "name": row[1],
3849
                               "data_source": data_source_dict.get(row[2], None),
3850
                               "object_type": row[3],
3851
                               "units": row[4],
3852
                               "high_limit": row[5],
3853
                               "low_limit": row[6],
3854
                               "higher_limit": row[7],
3855
                               "lower_limit": row[8],
3856
                               "ratio": Decimal(row[9]),
3857
                               "offset_constant": Decimal(row[10]),
3858
                               "is_trend": bool(row[11]),
3859
                               "is_virtual": bool(row[12]),
3860
                               "address": row[13],
3861
                               "description": row[14],
3862
                               "faults": row[15],
3863
                               "definitions": row[16]}
3864
                result_first.append(meta_result)
3865
        for item in result_first:
3866
            if item['id'] in equipment_pids:
3867
                result.insert(0,item)
3868
            else:
3869
                result.append(item)
3870
        resp.text = json.dumps(result)
3871
3872