Passed
Push — master ( bc2901...844492 )
by
unknown
11:09
created

core.command.CommandSend.on_options()   A

Complexity

Conditions 1

Size

Total Lines 5
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 5
dl 0
loc 5
rs 10
c 0
b 0
f 0
cc 1
nop 3
1
import uuid
2
from datetime import datetime, timedelta
3
import falcon
4
import mysql.connector
5
import simplejson as json
6
import paho.mqtt.client as mqtt
7
import time
8
from string import Template
9
from core.useractivity import user_logger, admin_control, access_control, api_key_control
10
import config
11
12
13
class CommandCollection:
14
    """
15
    Command Collection Resource
16
17
    This class handles CRUD operations for command collection.
18
    It provides endpoints for listing all commands and creating new commands.
19
    Commands represent MQTT-based control instructions for energy management systems.
20
    """
21
    def __init__(self):
22
        pass
23
24
    @staticmethod
25
    def on_options(req, resp):
26
        _ = req
27
        resp.status = falcon.HTTP_200
28
29 View Code Duplication
    @staticmethod
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
30
    def on_get(req, resp):
31
        if 'API-KEY' not in req.headers or \
32
                not isinstance(req.headers['API-KEY'], str) or \
33
                len(str.strip(req.headers['API-KEY'])) == 0:
34
            access_control(req)
35
        else:
36
            api_key_control(req)
37
38
        search_query = req.get_param('q', default=None)
39
        if search_query is not None:
40
            search_query = search_query.strip()
41
        else:
42
            search_query = ''
43
44
        cnx = mysql.connector.connect(**config.myems_system_db)
45
        cursor = cnx.cursor()
46
47
        query = (" SELECT id, name, uuid, "
48
                 "        topic, payload, set_value, description "
49
                 " FROM tbl_commands " )
50
51
        params=[]
52
        if search_query:
53
            query += " WHERE name LIKE %s  OR topic LIKE %s  OR  description LIKE %s "
54
            params = [f'%{search_query}%', f'%{search_query}%', f'%{search_query}%']
55
        query +=  " ORDER BY id "
56
        cursor.execute(query, params)
57
58
        rows = cursor.fetchall()
59
        cursor.close()
60
        cnx.close()
61
62
        result = list()
63
        if rows is not None and len(rows) > 0:
64
            for row in rows:
65
                meta_result = {"id": row[0],
66
                               "name": row[1],
67
                               "uuid": row[2],
68
                               "topic": row[3],
69
                               "payload": row[4],
70
                               "set_value": row[5],
71
                               "description": row[6]}
72
                result.append(meta_result)
73
74
        resp.text = json.dumps(result)
75
76
    @staticmethod
77
    @user_logger
78
    def on_post(req, resp):
79
        """Handles POST requests"""
80
        admin_control(req)
81
        try:
82
            raw_json = req.stream.read().decode('utf-8')
83
        except Exception as ex:
84
            print(str(ex))
85
            raise falcon.HTTPError(status=falcon.HTTP_400,
86
                                   title='API.BAD_REQUEST',
87
                                   description='API.FAILED_TO_READ_REQUEST_STREAM')
88
89
        new_values = json.loads(raw_json)
90
91
        if 'name' not in new_values['data'].keys() or \
92
                not isinstance(new_values['data']['name'], str) or \
93
                len(str.strip(new_values['data']['name'])) == 0:
94
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
95
                                   description='API.INVALID_COMMAND_NAME')
96
        name = str.strip(new_values['data']['name'])
97
98
        if 'topic' not in new_values['data'].keys() or \
99
                not isinstance(new_values['data']['topic'], str) or \
100
                len(str.strip(new_values['data']['topic'])) == 0:
101
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
102
                                   description='API.INVALID_TOPIC')
103
        topic = str.strip(new_values['data']['topic'])
104
105
        if 'payload' not in new_values['data'].keys() or \
106
                not isinstance(new_values['data']['payload'], str) or \
107
                len(str.strip(new_values['data']['payload'])) == 0:
108
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
109
                                   description='API.INVALID_PAYLOAD')
110
        payload = str.strip(new_values['data']['payload'])
111
112
        if 'set_value' not in new_values['data'].keys() or new_values['data']['set_value'] is None:
113
            set_value = None
114
        elif isinstance(new_values['data']['set_value'], float) or \
115
                isinstance(new_values['data']['set_value'], int):
116
            set_value = float(new_values['data']['set_value'])
117
        else:
118
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
119
                                   description='API.INVALID_SET_VALUE')
120
121
        if 'description' in new_values['data'].keys() and \
122
                new_values['data']['description'] is not None and \
123
                len(str(new_values['data']['description'])) > 0:
124
            description = str.strip(new_values['data']['description'])
125
        else:
126
            description = None
127
128
        cnx = mysql.connector.connect(**config.myems_system_db)
129
        cursor = cnx.cursor()
130
131
        cursor.execute(" SELECT name "
132
                       " FROM tbl_commands "
133
                       " WHERE name = %s ", (name,))
134
        if cursor.fetchone() is not None:
135
            cursor.close()
136
            cnx.close()
137
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
138
                                   description='API.COMMAND_NAME_IS_ALREADY_IN_USE')
139
140
        add_row = (" INSERT INTO tbl_commands "
141
                   "     (name, uuid, topic, payload, set_value, description) "
142
                   " VALUES (%s, %s, %s, %s, %s, %s) ")
143
144
        cursor.execute(add_row, (name,
145
                                 str(uuid.uuid4()),
146
                                 topic,
147
                                 payload,
148
                                 set_value,
149
                                 description))
150
        new_id = cursor.lastrowid
151
        cnx.commit()
152
        cursor.close()
153
        cnx.close()
154
155
        resp.status = falcon.HTTP_201
156
        resp.location = '/commands/' + str(new_id)
157
158
159
class CommandItem:
160
    def __init__(self):
161
        pass
162
163
    @staticmethod
164
    def on_options(req, resp, id_):
165
        _ = req
166
        resp.status = falcon.HTTP_200
167
        _ = id_
168
169 View Code Duplication
    @staticmethod
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
170
    def on_get(req, resp, id_):
171
        if 'API-KEY' not in req.headers or \
172
                not isinstance(req.headers['API-KEY'], str) or \
173
                len(str.strip(req.headers['API-KEY'])) == 0:
174
            access_control(req)
175
        else:
176
            api_key_control(req)
177
        if not id_.isdigit() or int(id_) <= 0:
178
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
179
                                   description='API.INVALID_COMMAND_ID')
180
181
        cnx = mysql.connector.connect(**config.myems_system_db)
182
        cursor = cnx.cursor()
183
184
        query = (" SELECT id, name, uuid, topic, payload, set_value, description "
185
                 " FROM tbl_commands "
186
                 " WHERE id = %s ")
187
        cursor.execute(query, (id_,))
188
        row = cursor.fetchone()
189
        cursor.close()
190
        cnx.close()
191
192
        if row is None:
193
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
194
                                   description='API.COMMAND_NOT_FOUND')
195
196
        result = {"id": row[0],
197
                  "name": row[1],
198
                  "uuid": row[2],
199
                  "topic": row[3],
200
                  "payload": row[4],
201
                  "set_value": row[5],
202
                  "description": row[6]}
203
        resp.text = json.dumps(result)
204
205
    @staticmethod
206
    @user_logger
207
    def on_delete(req, resp, id_):
208
        admin_control(req)
209
        if not id_.isdigit() or int(id_) <= 0:
210
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
211
                                   description='API.INVALID_COMMAND_ID')
212
213
        cnx = mysql.connector.connect(**config.myems_system_db)
214
        cursor = cnx.cursor()
215
216
        cursor.execute(" SELECT name "
217
                       " FROM tbl_commands "
218
                       " WHERE id = %s ", (id_,))
219
        if cursor.fetchone() is None:
220
            cursor.close()
221
            cnx.close()
222
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
223
                                   description='API.COMMAND_NOT_FOUND')
224
225
        # check relation with meter
226
        cursor.execute(" SELECT meter_id "
227
                       " FROM tbl_meters_commands "
228
                       " WHERE command_id = %s ",
229
                       (id_,))
230
        rows = cursor.fetchall()
231
        if rows is not None and len(rows) > 0:
232
            cursor.close()
233
            cnx.close()
234
            raise falcon.HTTPError(status=falcon.HTTP_400,
235
                                   title='API.BAD_REQUEST',
236
                                   description='API.THERE_IS_RELATION_WITH_METERS')
237
238
        # check relation with space
239
        cursor.execute(" SELECT space_id "
240
                       " FROM tbl_spaces_commands "
241
                       " WHERE command_id = %s ",
242
                       (id_,))
243
        rows_spaces = cursor.fetchall()
244
        if rows_spaces is not None and len(rows_spaces) > 0:
245
            cursor.close()
246
            cnx.close()
247
            raise falcon.HTTPError(status=falcon.HTTP_400,
248
                                   title='API.BAD_REQUEST',
249
                                   description='API.THERE_IS_RELATION_WITH_SPACES')
250
251
        # check relation with equipment
252
        cursor.execute(" SELECT equipment_id "
253
                       " FROM tbl_equipments_commands "
254
                       " WHERE command_id = %s ",
255
                       (id_,))
256
        rows = cursor.fetchall()
257
        if rows is not None and len(rows) > 0:
258
            cursor.close()
259
            cnx.close()
260
            raise falcon.HTTPError(status=falcon.HTTP_400,
261
                                   title='API.BAD_REQUEST',
262
                                   description='API.THERE_IS_RELATION_WITH_EQUIPMENTS')
263
264
        # check relation with combined equipment
265
        cursor.execute(" SELECT combined_equipment_id "
266
                       " FROM tbl_combined_equipments_commands "
267
                       " WHERE command_id = %s ",
268
                       (id_,))
269
        rows = cursor.fetchall()
270
        if rows is not None and len(rows) > 0:
271
            cursor.close()
272
            cnx.close()
273
            raise falcon.HTTPError(status=falcon.HTTP_400,
274
                                   title='API.BAD_REQUEST',
275
                                   description='API.THERE_IS_RELATION_WITH_COMBINED_EQUIPMENTS')
276
277
        # check relation with tenant
278
        cursor.execute(" SELECT tenant_id "
279
                       " FROM tbl_tenants_commands "
280
                       " WHERE command_id = %s ",
281
                       (id_,))
282
        rows = cursor.fetchall()
283
        if rows is not None and len(rows) > 0:
284
            cursor.close()
285
            cnx.close()
286
            raise falcon.HTTPError(status=falcon.HTTP_400,
287
                                   title='API.BAD_REQUEST',
288
                                   description='API.THERE_IS_RELATION_WITH_TENANTS')
289
290
        # check relation with store
291
        cursor.execute(" SELECT store_id "
292
                       " FROM tbl_stores_commands "
293
                       " WHERE command_id = %s ",
294
                       (id_,))
295
        rows = cursor.fetchall()
296
        if rows is not None and len(rows) > 0:
297
            cursor.close()
298
            cnx.close()
299
            raise falcon.HTTPError(status=falcon.HTTP_400,
300
                                   title='API.BAD_REQUEST',
301
                                   description='API.THERE_IS_RELATION_WITH_STORES')
302
303
        # check relation with shopfloor
304
        cursor.execute(" SELECT shopfloor_id "
305
                       " FROM tbl_shopfloors_commands "
306
                       " WHERE command_id = %s ",
307
                       (id_,))
308
        rows = cursor.fetchall()
309
        if rows is not None and len(rows) > 0:
310
            cursor.close()
311
            cnx.close()
312
            raise falcon.HTTPError(status=falcon.HTTP_400,
313
                                   title='API.BAD_REQUEST',
314
                                   description='API.THERE_IS_RELATION_WITH_SHOPFLOORS')
315
316
        # check relation with energy storage container
317
        cursor.execute(" SELECT energy_storage_container_id "
318
                       " FROM tbl_energy_storage_containers_commands "
319
                       " WHERE command_id = %s ",
320
                       (id_,))
321
        rows = cursor.fetchall()
322
        if rows is not None and len(rows) > 0:
323
            cursor.close()
324
            cnx.close()
325
            raise falcon.HTTPError(status=falcon.HTTP_400,
326
                                   title='API.BAD_REQUEST',
327
                                   description='API.THERE_IS_RELATION_WITH_ENERGY_STORAGE_CONTAINERS')
328
329
        # check relation with microgrid
330
        cursor.execute(" SELECT microgrid_id "
331
                       " FROM tbl_microgrids_commands "
332
                       " WHERE command_id = %s ",
333
                       (id_,))
334
        rows = cursor.fetchall()
335
        if rows is not None and len(rows) > 0:
336
            cursor.close()
337
            cnx.close()
338
            raise falcon.HTTPError(status=falcon.HTTP_400,
339
                                   title='API.BAD_REQUEST',
340
                                   description='API.THERE_IS_RELATION_WITH_MICROGRIDS')
341
342
        # todo: check relation with points
343
344
        cursor.execute(" DELETE FROM tbl_commands WHERE id = %s ", (id_,))
345
        cnx.commit()
346
347
        cursor.close()
348
        cnx.close()
349
350
        resp.status = falcon.HTTP_204
351
352
    @staticmethod
353
    @user_logger
354
    def on_put(req, resp, id_):
355
        """Handles PUT requests"""
356
        admin_control(req)
357
        try:
358
            raw_json = req.stream.read().decode('utf-8')
359
        except Exception as ex:
360
            print(str(ex))
361
            raise falcon.HTTPError(status=falcon.HTTP_400,
362
                                   title='API.BAD_REQUEST',
363
                                   description='API.FAILED_TO_READ_REQUEST_STREAM')
364
365
        if not id_.isdigit() or int(id_) <= 0:
366
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
367
                                   description='API.INVALID_COMMAND_ID')
368
369
        new_values = json.loads(raw_json)
370
371
        if 'name' not in new_values['data'].keys() or \
372
                not isinstance(new_values['data']['name'], str) or \
373
                len(str.strip(new_values['data']['name'])) == 0:
374
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
375
                                   description='API.INVALID_COMMAND_NAME')
376
        name = str.strip(new_values['data']['name'])
377
378
        if 'topic' not in new_values['data'].keys() or \
379
                not isinstance(new_values['data']['topic'], str) or \
380
                len(str.strip(new_values['data']['topic'])) == 0:
381
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
382
                                   description='API.INVALID_TOPIC')
383
        topic = str.strip(new_values['data']['topic'])
384
385
        if 'payload' not in new_values['data'].keys() or \
386
                not isinstance(new_values['data']['payload'], str) or \
387
                len(str.strip(new_values['data']['payload'])) == 0:
388
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
389
                                   description='API.INVALID_PAYLOAD')
390
        payload = str.strip(new_values['data']['payload'])
391
392
        if 'set_value' not in new_values['data'].keys() or new_values['data']['set_value'] is None:
393
            set_value = None
394
        elif isinstance(new_values['data']['set_value'], float) or \
395
                isinstance(new_values['data']['set_value'], int):
396
            set_value = float(new_values['data']['set_value'])
397
        else:
398
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
399
                                   description='API.INVALID_SET_VALUE')
400
401
        if 'description' in new_values['data'].keys() and \
402
                new_values['data']['description'] is not None and \
403
                len(str(new_values['data']['description'])) > 0:
404
            description = str.strip(new_values['data']['description'])
405
        else:
406
            description = None
407
408
        cnx = mysql.connector.connect(**config.myems_system_db)
409
        cursor = cnx.cursor()
410
411
        cursor.execute(" SELECT name "
412
                       " FROM tbl_commands "
413
                       " WHERE id = %s ", (id_,))
414
        if cursor.fetchone() is None:
415
            cursor.close()
416
            cnx.close()
417
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
418
                                   description='API.COMMAND_NOT_FOUND')
419
420
        cursor.execute(" SELECT name "
421
                       " FROM tbl_commands "
422
                       " WHERE name = %s AND id != %s ", (name, id_))
423
        if cursor.fetchone() is not None:
424
            cursor.close()
425
            cnx.close()
426
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
427
                                   description='API.COMMAND_NAME_IS_ALREADY_IN_USE')
428
429
        update_row = (" UPDATE tbl_commands "
430
                      " SET name = %s, topic = %s, payload = %s, set_value = %s, description = %s "
431
                      " WHERE id = %s ")
432
        cursor.execute(update_row, (name,
433
                                    topic,
434
                                    payload,
435
                                    set_value,
436
                                    description,
437
                                    id_,))
438
        cnx.commit()
439
440
        cursor.close()
441
        cnx.close()
442
443
        resp.status = falcon.HTTP_200
444
445
446
class CommandSend:
447
    def __init__(self):
448
        pass
449
450
    @staticmethod
451
    def on_options(req, resp, id_):
452
        _ = req
453
        resp.status = falcon.HTTP_200
454
        _ = id_
455
456
    @staticmethod
457
    def on_put(req, resp, id_):
458
        """Handles GET requests"""
459
        admin_control(req)
460
        # Get command by ID
461
        if not id_.isdigit() or int(id_) <= 0:
462
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
463
                                   description='API.INVALID_COMMAND_ID')
464
465
        try:
466
            raw_json = req.stream.read().decode('utf-8')
467
        except Exception as ex:
468
            print(str(ex))
469
            raise falcon.HTTPError(status=falcon.HTTP_400,
470
                                   title='API.BAD_REQUEST',
471
                                   description='API.FAILED_TO_READ_REQUEST_STREAM')
472
473
        new_values = json.loads(raw_json)
474
475
        if 'set_value' not in new_values['data'].keys() or new_values['data']['set_value'] is None:
476
            set_value = None
477
        elif isinstance(new_values['data']['set_value'], float):
478
            set_value = float(new_values['data']['set_value'])
479
        elif isinstance(new_values['data']['set_value'], int):
480
            set_value = int(new_values['data']['set_value'])
481
        else:
482
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
483
                                   description='API.INVALID_SET_VALUE')
484
485
        cnx = mysql.connector.connect(**config.myems_system_db)
486
        cursor = cnx.cursor()
487
488
        query = (" SELECT id, name, uuid, topic, payload, set_value "
489
                 " FROM tbl_commands "
490
                 " WHERE id = %s ")
491
        cursor.execute(query, (id_,))
492
        row = cursor.fetchone()
493
494
        if row is None:
495
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
496
                                   description='API.COMMAND_NOT_FOUND')
497
498
        command = {"id": row[0],
499
                   "name": row[1],
500
                   "uuid": row[2],
501
                   "topic": row[3],
502
                   "payload": row[4],
503
                   "set_value": set_value if set_value is not None else row[5]}
504
505
        update_row = (" UPDATE tbl_commands "
506
                      " SET set_value = %s "
507
                      " WHERE id = %s ")
508
        cursor.execute(update_row, (set_value,
509
                                    id_,))
510
        cnx.commit()
511
512
        cursor.close()
513
        cnx.close()
514
515
        mqc = None
516
        try:
517
            mqc = mqtt.Client(callback_api_version=mqtt.CallbackAPIVersion.VERSION2,
518
                              client_id='MYEMS' + "-" + str(time.time()),
519
                              clean_session=None,
520
                              userdata=None,
521
                              protocol=mqtt.MQTTv5,
522
                              transport='tcp',
523
                              reconnect_on_failure=True,
524
                              manual_ack=False)
525
            mqc.username_pw_set(config.myems_mqtt_broker['username'], config.myems_mqtt_broker['password'])
526
            mqc.connect(config.myems_mqtt_broker['host'], config.myems_mqtt_broker['port'], 60)
527
        except Exception as e:
528
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
529
                                   description='API.MQTT_CONNECTION_ERROR')
530
531
        try:
532
            if command['set_value'] is not None:
533
                payload = Template(command['payload']).substitute(s1=str(command['set_value']))
534
            else:
535
                payload = Template(command['payload']).substitute(s1=str(0))
536
            print('payload=' + str(payload))
537
            mqc.publish(command['topic'], payload=payload)
538
        except Exception as e:
539
            print(str(e))
540
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
541
                                   description='API.MQTT_PUBLISH_ERROR')
542
543
        resp.text = json.dumps('success')
544
545
546
class CommandExport:
547
    def __init__(self):
548
        pass
549
550
    @staticmethod
551
    def on_options(req, resp, id_):
552
        _ = req
553
        resp.status = falcon.HTTP_200
554
        _ = id_
555
556 View Code Duplication
    @staticmethod
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
557
    def on_get(req, resp, id_):
558
        if 'API-KEY' not in req.headers or \
559
                not isinstance(req.headers['API-KEY'], str) or \
560
                len(str.strip(req.headers['API-KEY'])) == 0:
561
            access_control(req)
562
        else:
563
            api_key_control(req)
564
        if not id_.isdigit() or int(id_) <= 0:
565
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
566
                                   description='API.INVALID_COMMAND_ID')
567
568
        cnx = mysql.connector.connect(**config.myems_system_db)
569
        cursor = cnx.cursor()
570
571
        query = (" SELECT id, name, uuid, topic, payload, set_value, description "
572
                 " FROM tbl_commands "
573
                 " WHERE id = %s ")
574
        cursor.execute(query, (id_,))
575
        row = cursor.fetchone()
576
        cursor.close()
577
        cnx.close()
578
579
        if row is None:
580
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
581
                                   description='API.COMMAND_NOT_FOUND')
582
583
        result = {"id": row[0],
584
                  "name": row[1],
585
                  "uuid": row[2],
586
                  "topic": row[3],
587
                  "payload": row[4],
588
                  "set_value": row[5],
589
                  "description": row[6]}
590
        resp.text = json.dumps(result)
591
592
593
class CommandImport:
594
    def __init__(self):
595
        pass
596
597
    @staticmethod
598
    def on_options(req, resp):
599
        _ = req
600
        resp.status = falcon.HTTP_200
601
602
    @staticmethod
603
    @user_logger
604
    def on_post(req, resp):
605
        """Handles POST requests"""
606
        admin_control(req)
607
        try:
608
            raw_json = req.stream.read().decode('utf-8')
609
        except Exception as ex:
610
            print(str(ex))
611
            raise falcon.HTTPError(status=falcon.HTTP_400,
612
                                   title='API.BAD_REQUEST',
613
                                   description='API.FAILED_TO_READ_REQUEST_STREAM')
614
615
        new_values = json.loads(raw_json)
616
617
        if 'name' not in new_values.keys() or \
618
                not isinstance(new_values['name'], str) or \
619
                len(str.strip(new_values['name'])) == 0:
620
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
621
                                   description='API.INVALID_COMMAND_NAME')
622
        name = str.strip(new_values['name'])
623
624
        if 'topic' not in new_values.keys() or \
625
                not isinstance(new_values['topic'], str) or \
626
                len(str.strip(new_values['topic'])) == 0:
627
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
628
                                   description='API.INVALID_TOPIC')
629
        topic = str.strip(new_values['topic'])
630
631
        if 'payload' not in new_values.keys() or \
632
                not isinstance(new_values['payload'], str) or \
633
                len(str.strip(new_values['payload'])) == 0:
634
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
635
                                   description='API.INVALID_PAYLOAD')
636
        payload = str.strip(new_values['payload'])
637
638
        if 'set_value' not in new_values.keys() or new_values['set_value'] is None:
639
            set_value = None
640
        elif isinstance(new_values['set_value'], float) or \
641
                isinstance(new_values['set_value'], int):
642
            set_value = float(new_values['set_value'])
643
        else:
644
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
645
                                   description='API.INVALID_SET_VALUE')
646
647
        if 'description' in new_values.keys() and \
648
                new_values['description'] is not None and \
649
                len(str(new_values['description'])) > 0:
650
            description = str.strip(new_values['description'])
651
        else:
652
            description = None
653
654
        cnx = mysql.connector.connect(**config.myems_system_db)
655
        cursor = cnx.cursor()
656
657
        cursor.execute(" SELECT name "
658
                       " FROM tbl_commands "
659
                       " WHERE name = %s ", (name,))
660
        if cursor.fetchone() is not None:
661
            cursor.close()
662
            cnx.close()
663
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
664
                                   description='API.COMMAND_NAME_IS_ALREADY_IN_USE')
665
666
        add_row = (" INSERT INTO tbl_commands "
667
                   "     (name, uuid, topic, payload, set_value, description) "
668
                   " VALUES (%s, %s, %s, %s, %s, %s) ")
669
670
        cursor.execute(add_row, (name,
671
                                 str(uuid.uuid4()),
672
                                 topic,
673
                                 payload,
674
                                 set_value,
675
                                 description))
676
        new_id = cursor.lastrowid
677
        cnx.commit()
678
        cursor.close()
679
        cnx.close()
680
681
        resp.status = falcon.HTTP_201
682
        resp.location = '/commands/' + str(new_id)
683
684
685
class CommandClone:
686
    def __init__(self):
687
        pass
688
689
    @staticmethod
690
    def on_options(req, resp, id_):
691
        _ = req
692
        resp.status = falcon.HTTP_200
693
        _ = id_
694
695
    @staticmethod
696
    @user_logger
697
    def on_post(req, resp, id_):
698
        admin_control(req)
699
        if not id_.isdigit() or int(id_) <= 0:
700
            raise falcon.HTTPError(status=falcon.HTTP_400, title='API.BAD_REQUEST',
701
                                   description='API.INVALID_COMMAND_ID')
702
703
        cnx = mysql.connector.connect(**config.myems_system_db)
704
        cursor = cnx.cursor()
705
706
        query = (" SELECT id, name, uuid, topic, payload, set_value, description "
707
                 " FROM tbl_commands "
708
                 " WHERE id = %s ")
709
        cursor.execute(query, (id_,))
710
        row = cursor.fetchone()
711
712
        if row is None:
713
            raise falcon.HTTPError(status=falcon.HTTP_404, title='API.NOT_FOUND',
714
                                   description='API.COMMAND_NOT_FOUND')
715
716
        result = {"id": row[0],
717
                  "name": row[1],
718
                  "uuid": row[2],
719
                  "topic": row[3],
720
                  "payload": row[4],
721
                  "set_value": row[5],
722
                  "description": row[6]}
723
        add_row = (" INSERT INTO tbl_commands "
724
                   "     (name, uuid, topic, payload, set_value, description) "
725
                   " VALUES (%s, %s, %s, %s, %s, %s) ")
726
727
        timezone_offset = int(config.utc_offset[1:3]) * 60 + int(config.utc_offset[4:6])
728
        if config.utc_offset[0] == '-':
729
            timezone_offset = -timezone_offset
730
        new_name = (str.strip(result['name']) +
731
                    (datetime.utcnow() + timedelta(minutes=timezone_offset)).isoformat(sep='-', timespec='seconds'))
732
        cursor.execute(add_row, (new_name,
733
                                 str(uuid.uuid4()),
734
                                 result['topic'],
735
                                 result['payload'],
736
                                 result['set_value'],
737
                                 result['description']))
738
        new_id = cursor.lastrowid
739
        cnx.commit()
740
        cursor.close()
741
        cnx.close()
742
743
        resp.status = falcon.HTTP_201
744
        resp.location = '/commands/' + str(new_id)
745
746