core.command.CommandSend.on_put()   F
last analyzed

Complexity

Conditions 13

Size

Total Lines 88
Code Lines 68

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 68
dl 0
loc 88
rs 3.9872
c 0
b 0
f 0
cc 13
nop 3

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

Complexity

Complex classes like core.command.CommandSend.on_put() often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

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