epyt-flow 0.1.1__py3-none-any.whl → 0.3.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (31) hide show
  1. epyt_flow/EPANET/compile_linux.sh +4 -0
  2. epyt_flow/EPANET/compile_macos.sh +4 -0
  3. epyt_flow/VERSION +1 -1
  4. epyt_flow/__init__.py +29 -18
  5. epyt_flow/data/benchmarks/leakdb.py +7 -12
  6. epyt_flow/data/networks.py +404 -40
  7. epyt_flow/rest_api/base_handler.py +14 -0
  8. epyt_flow/rest_api/scada_data/__init__.py +0 -0
  9. epyt_flow/rest_api/{scada_data_handler.py → scada_data/data_handlers.py} +3 -162
  10. epyt_flow/rest_api/scada_data/export_handlers.py +140 -0
  11. epyt_flow/rest_api/scada_data/handlers.py +209 -0
  12. epyt_flow/rest_api/scenario/__init__.py +0 -0
  13. epyt_flow/rest_api/scenario/event_handlers.py +118 -0
  14. epyt_flow/rest_api/{scenario_handler.py → scenario/handlers.py} +86 -67
  15. epyt_flow/rest_api/scenario/simulation_handlers.py +174 -0
  16. epyt_flow/rest_api/scenario/uncertainty_handlers.py +118 -0
  17. epyt_flow/rest_api/server.py +61 -24
  18. epyt_flow/simulation/events/leakages.py +27 -17
  19. epyt_flow/simulation/scada/scada_data.py +545 -14
  20. epyt_flow/simulation/scada/scada_data_export.py +39 -12
  21. epyt_flow/simulation/scenario_config.py +14 -20
  22. epyt_flow/simulation/scenario_simulator.py +358 -114
  23. epyt_flow/simulation/sensor_config.py +693 -37
  24. epyt_flow/topology.py +149 -8
  25. epyt_flow/utils.py +75 -18
  26. {epyt_flow-0.1.1.dist-info → epyt_flow-0.3.0.dist-info}/METADATA +33 -5
  27. {epyt_flow-0.1.1.dist-info → epyt_flow-0.3.0.dist-info}/RECORD +30 -22
  28. epyt_flow/EPANET/compile.sh +0 -4
  29. {epyt_flow-0.1.1.dist-info → epyt_flow-0.3.0.dist-info}/LICENSE +0 -0
  30. {epyt_flow-0.1.1.dist-info → epyt_flow-0.3.0.dist-info}/WHEEL +0 -0
  31. {epyt_flow-0.1.1.dist-info → epyt_flow-0.3.0.dist-info}/top_level.txt +0 -0
@@ -11,6 +11,20 @@ class BaseHandler():
11
11
  """
12
12
  Base class for all REST API handlers.
13
13
  """
14
+ def send_error(self, resp: falcon.Response, error_msg: str) -> None:
15
+ """
16
+ Sends an error message back.
17
+
18
+ Parameters
19
+ ----------
20
+ resp : `falcon.Response`
21
+ Response instance.
22
+ error_msg : `str`
23
+ Error message.
24
+ """
25
+ resp.status = falcon.HTTP_BAD_REQUEST
26
+ resp.data = error_msg.encode()
27
+
14
28
  def send_invalid_resource_id_error(self, resp: falcon.Response) -> None:
15
29
  """
16
30
  Sends an error that th given resource ID (e.g. scenario ID, or SCADA data ID) is invalid.
File without changes
@@ -1,170 +1,11 @@
1
1
  """
2
- The module provides all handlers for SCADA data requests.
2
+ This module provides REST API handlers for accessing the final sensor readings
3
+ (e.g. pressure, flow rate, etc.).
3
4
  """
4
5
  import warnings
5
6
  import falcon
6
7
 
7
- from .base_handler import BaseHandler
8
- from .res_manager import ResourceManager
9
- from ..simulation import SensorConfig, SensorFault
10
-
11
-
12
- class ScadaDataManager(ResourceManager):
13
- """
14
- Class for managing SCADA data.
15
- """
16
-
17
-
18
- class ScadaDataBaseHandler(BaseHandler):
19
- """
20
- Base class for all handlers concerning SCADA data.
21
-
22
- Parameters
23
- ----------
24
- scada_data_mgr : `~epyt_flow.rest_api.scenario_handler.ScadaDataBaseHandler`
25
- SCADA data manager.
26
- """
27
- def __init__(self, scada_data_mgr: ScadaDataManager):
28
- self.scada_data_mgr = scada_data_mgr
29
-
30
-
31
- class ScadaDataRemoveHandler(ScadaDataBaseHandler):
32
- """
33
- Class for handling a DELETE request for a given SCADA data instance.
34
- """
35
- def on_delete(self, _, resp: falcon.Response, data_id: str) -> None:
36
- """
37
- Deletes a given SCADA data instance.
38
-
39
- Parameters
40
- ----------
41
- resp : `falcon.Response`
42
- Response instance.
43
- data_id : `str`
44
- UUID of the SCADA data instance.
45
- """
46
- try:
47
- if self.scada_data_mgr.validate_uuid(data_id) is False:
48
- self.send_invalid_resource_id_error(resp)
49
- return
50
-
51
- self.scada_data_mgr.remove(data_id)
52
- except Exception as ex:
53
- warnings.warn(str(ex))
54
- resp.status = falcon.HTTP_INTERNAL_SERVER_ERROR
55
-
56
-
57
- class ScadaDataSensorConfigHandler(ScadaDataBaseHandler):
58
- """
59
- Class for handling GET and POST requests for the sensor configuration
60
- of a given SCADA data instance.
61
- """
62
- def on_get(self, _, resp: falcon.Response, data_id: str) -> None:
63
- """
64
- Gets the sensor configuration of a given SCADA data instance.
65
-
66
- Parameters
67
- ----------
68
- resp : `falcon.Response`
69
- Response instance.
70
- data_id : `str`
71
- UUID of the SCADA data.
72
- """
73
- try:
74
- if self.scada_data_mgr.validate_uuid(data_id) is False:
75
- self.send_invalid_resource_id_error(resp)
76
- return
77
-
78
- my_sensor_config = self.scada_data_mgr.get(data_id).sensor_config
79
- self.send_json_response(resp, my_sensor_config)
80
- except Exception as ex:
81
- warnings.warn(str(ex))
82
- resp.status = falcon.HTTP_INTERNAL_SERVER_ERROR
83
-
84
- def on_post(self, req: falcon.Request, resp: falcon.Response, data_id: str) -> None:
85
- """
86
- Sets the sensor configuration of a given SCADA data instance.
87
-
88
- Parameters
89
- ----------
90
- req : `falcon.Request`
91
- Request instance.
92
- resp : `falcon.Response`
93
- Response instance.
94
- data_id : `str`
95
- UUID of the SCADA data.
96
- """
97
- try:
98
- if self.scada_data_mgr.validate_uuid(data_id) is False:
99
- self.send_invalid_resource_id_error(resp)
100
- return
101
-
102
- sensor_config = self.load_json_data_from_request(req)
103
- if not isinstance(sensor_config, SensorConfig):
104
- self.send_json_parsing_error(resp)
105
- return
106
-
107
- self.scada_data_mgr.get(data_id).sensor_config = sensor_config
108
- except Exception as ex:
109
- warnings.warn(str(ex))
110
- resp.status = falcon.HTTP_INTERNAL_SERVER_ERROR
111
-
112
-
113
- class ScadaDataSensorFaultsHandler(ScadaDataBaseHandler):
114
- """
115
- Class for handling GET and POST requests concerning sensor faults in a
116
- given SCADA data instance.
117
- """
118
- def on_get(self, _, resp: falcon.Response, data_id: str) -> None:
119
- """
120
- Gets all sensor faults of a given SCADA data instance.
121
-
122
- Parameters
123
- ----------
124
- resp : `falcon.Response`
125
- Response instance.
126
- data_id : `str`
127
- UUID of the SCADA data.
128
- """
129
- try:
130
- if self.scada_data_mgr.validate_uuid(data_id) is False:
131
- self.send_invalid_resource_id_error(resp)
132
- return
133
-
134
- sensor_faults = self.scada_data_mgr.get(data_id).sensor_faults
135
- self.send_json_response(resp, sensor_faults)
136
- except Exception as ex:
137
- warnings.warn(str(ex))
138
- resp.status = falcon.HTTP_INTERNAL_SERVER_ERROR
139
-
140
- def on_post(self, req: falcon.Request, resp: falcon.Response, data_id: str) -> None:
141
- """
142
- Sets (i.e. overrides) the sensor faults in a given SCADA data instance.
143
-
144
- Parameters
145
- ----------
146
- req : `falcon.Request`
147
- Request instance.
148
- resp : `falcon.Response`
149
- Response instance.
150
- data_id : `str`
151
- UUID of the SCADA data.
152
- """
153
- try:
154
- if self.scada_data_mgr.validate_uuid(data_id) is False:
155
- self.send_invalid_resource_id_error(resp)
156
- return
157
-
158
- sensor_faults = self.load_json_data_from_request(req)
159
- if not isinstance(sensor_faults, list) or \
160
- any(not isinstance(e, SensorFault) for e in sensor_faults):
161
- self.send_json_parsing_error(resp)
162
- return
163
-
164
- self.scada_data_mgr.get(data_id).sensor_faults = sensor_faults
165
- except Exception as ex:
166
- warnings.warn(str(ex))
167
- resp.status = falcon.HTTP_INTERNAL_SERVER_ERROR
8
+ from .handlers import ScadaDataBaseHandler
168
9
 
169
10
 
170
11
  class ScadaDataPressuresHandler(ScadaDataBaseHandler):
@@ -0,0 +1,140 @@
1
+ """
2
+ This module provides REST API handlers for exporting a given SCADA data instance.
3
+ """
4
+ import os
5
+ from abc import abstractmethod
6
+ import warnings
7
+ import falcon
8
+
9
+ from .handlers import ScadaDataBaseHandler
10
+ from ...utils import get_temp_folder
11
+ from ...simulation.scada import ScadaData, ScadaDataNumpyExport, ScadaDataMatlabExport, \
12
+ ScadaDataXlsxExport
13
+
14
+
15
+ class ScadaDataBaseExportHandler(ScadaDataBaseHandler):
16
+ """
17
+ Base handler for exporting a given SCADA data instance.
18
+ """
19
+ def __init__(self, file_ext: str, **kwds):
20
+ self.__file_ext = file_ext
21
+
22
+ super().__init__(**kwds)
23
+
24
+ def create_temp_file_path(self, data_id: str, file_ext: str) -> None:
25
+ """
26
+ Returns a path to a temporary file for storing the SCADA data instance.
27
+
28
+ Parameters
29
+ ----------
30
+ data_id : `str`
31
+ UUID of the SCADA data.
32
+ file_ext : `str`
33
+ File extension.
34
+ """
35
+ return os.path.join(get_temp_folder(), f"{data_id}.{file_ext}")
36
+
37
+ def send_temp_file(self, resp: falcon.Response, tmp_file: str,
38
+ content_type: str = "application/octet-stream") -> None:
39
+ """
40
+ Sends a given file (`tmp_file`) to the the client.
41
+
42
+ Parameters
43
+ ----------
44
+ resp : `falcon.Response`
45
+ Response instance.
46
+ tmp_file : `str`
47
+ Path to the temporary file to be send.
48
+ """
49
+ resp.status = falcon.HTTP_200
50
+ resp.content_type = content_type
51
+ with open(tmp_file, 'rb') as f:
52
+ resp.text = f.read()
53
+
54
+ @abstractmethod
55
+ def export(self, scada_data: ScadaData, tmp_file: str) -> None:
56
+ """
57
+ Exports a given SCADA data instance to a temporary file.
58
+
59
+ Parameters
60
+ ----------
61
+ scada_data : :class:`~epyt_flow.simulation.scada.scada_data.ScadaData`
62
+ SCADA data instance to be exported.
63
+ tmp_file : `str`
64
+ Path to temporary file.
65
+ """
66
+ raise NotImplementedError()
67
+
68
+ def on_get(self, _, resp: falcon.Response, data_id: str) -> None:
69
+ """
70
+ Gets the given SCADA data instance.
71
+
72
+ Parameters
73
+ ----------
74
+ resp : `falcon.Response`
75
+ Response instance.
76
+ data_id : `str`
77
+ UUID of the SCADA data.
78
+ """
79
+ try:
80
+ if self.scada_data_mgr.validate_uuid(data_id) is False:
81
+ self.send_invalid_resource_id_error(resp)
82
+ return
83
+
84
+ my_scada_data = self.scada_data_mgr.get(data_id)
85
+
86
+ tmp_file = self.create_temp_file_path(data_id, self.__file_ext)
87
+ self.export(my_scada_data, tmp_file)
88
+
89
+ self.send_temp_file(resp, tmp_file)
90
+
91
+ os.remove(tmp_file)
92
+ except Exception as ex:
93
+ warnings.warn(str(ex))
94
+ resp.status = falcon.HTTP_INTERNAL_SERVER_ERROR
95
+
96
+
97
+ class ScadaDataExportHandler(ScadaDataBaseExportHandler):
98
+ """
99
+ Class for handling a GET requests for exporting a given SCADA data instance
100
+ to an .epytflow_scada_data file.
101
+ """
102
+ def __init__(self, **kwds):
103
+ super().__init__(file_ext=".epytflow_scada_data", **kwds)
104
+
105
+ def export(self, scada_data: ScadaData, tmp_file: str) -> None:
106
+ scada_data.save_to_file(tmp_file)
107
+
108
+
109
+ class ScadaDataXlsxExportHandler(ScadaDataBaseExportHandler):
110
+ """
111
+ Class for handling a GET requests for exporting a given SCADA data instance to a .xlsx file.
112
+ """
113
+ def __init__(self, **kwds):
114
+ super().__init__(file_ext=".xlsx", **kwds)
115
+
116
+ def export(self, scada_data: ScadaData, tmp_file: str) -> None:
117
+ ScadaDataXlsxExport(tmp_file).export(scada_data)
118
+
119
+
120
+ class ScadaDataNumpyExportHandler(ScadaDataBaseExportHandler):
121
+ """
122
+ Class for handling a GET requests for exporting a given SCADA data instance to Numpy data file.
123
+ """
124
+ def __init__(self, **kwds):
125
+ super().__init__(file_ext=".npz", **kwds)
126
+
127
+ def export(self, scada_data: ScadaData, tmp_file: str) -> None:
128
+ ScadaDataNumpyExport(tmp_file).export(scada_data)
129
+
130
+
131
+ class ScadaDataMatlabExportHandler(ScadaDataBaseExportHandler):
132
+ """
133
+ Class for handling a GET requests for exporting a given SCADA data instance
134
+ to a Matlab data file.
135
+ """
136
+ def __init__(self, **kwds):
137
+ super().__init__(file_ext=".mat", **kwds)
138
+
139
+ def export(self, scada_data: ScadaData, tmp_file: str) -> None:
140
+ ScadaDataMatlabExport(tmp_file).export(scada_data)
@@ -0,0 +1,209 @@
1
+ """
2
+ The module provides REST API handlers for some SCADA data requests.
3
+ """
4
+ import warnings
5
+ import falcon
6
+
7
+ from ..base_handler import BaseHandler
8
+ from ..res_manager import ResourceManager
9
+ from ...simulation import SensorConfig, SensorFault
10
+
11
+
12
+ class ScadaDataManager(ResourceManager):
13
+ """
14
+ Class for managing SCADA data.
15
+ """
16
+
17
+
18
+ class ScadaDataBaseHandler(BaseHandler):
19
+ """
20
+ Base class for all handlers concerning SCADA data.
21
+
22
+ Parameters
23
+ ----------
24
+ scada_data_mgr : :class:`~epyt_flow.rest_api.scada_data.handlers.ScadaDataManager`
25
+ SCADA data manager.
26
+ """
27
+ def __init__(self, scada_data_mgr: ScadaDataManager):
28
+ self.scada_data_mgr = scada_data_mgr
29
+
30
+
31
+ class ScadaDataRemoveHandler(ScadaDataBaseHandler):
32
+ """
33
+ Class for handling a DELETE request for a given SCADA data instance.
34
+ """
35
+ def on_delete(self, _, resp: falcon.Response, data_id: str) -> None:
36
+ """
37
+ Deletes a given SCADA data instance.
38
+
39
+ Parameters
40
+ ----------
41
+ resp : `falcon.Response`
42
+ Response instance.
43
+ data_id : `str`
44
+ UUID of the SCADA data instance.
45
+ """
46
+ try:
47
+ if self.scada_data_mgr.validate_uuid(data_id) is False:
48
+ self.send_invalid_resource_id_error(resp)
49
+ return
50
+
51
+ self.scada_data_mgr.remove(data_id)
52
+ except Exception as ex:
53
+ warnings.warn(str(ex))
54
+ resp.status = falcon.HTTP_INTERNAL_SERVER_ERROR
55
+
56
+
57
+ class ScadaDataSensorConfigHandler(ScadaDataBaseHandler):
58
+ """
59
+ Class for handling GET and POST requests for the sensor configuration
60
+ of a given SCADA data instance.
61
+ """
62
+ def on_get(self, _, resp: falcon.Response, data_id: str) -> None:
63
+ """
64
+ Gets the sensor configuration of a given SCADA data instance.
65
+
66
+ Parameters
67
+ ----------
68
+ resp : `falcon.Response`
69
+ Response instance.
70
+ data_id : `str`
71
+ UUID of the SCADA data.
72
+ """
73
+ try:
74
+ if self.scada_data_mgr.validate_uuid(data_id) is False:
75
+ self.send_invalid_resource_id_error(resp)
76
+ return
77
+
78
+ my_sensor_config = self.scada_data_mgr.get(data_id).sensor_config
79
+ self.send_json_response(resp, my_sensor_config)
80
+ except Exception as ex:
81
+ warnings.warn(str(ex))
82
+ resp.status = falcon.HTTP_INTERNAL_SERVER_ERROR
83
+
84
+ def on_post(self, req: falcon.Request, resp: falcon.Response, data_id: str) -> None:
85
+ """
86
+ Sets the sensor configuration of a given SCADA data instance.
87
+
88
+ Parameters
89
+ ----------
90
+ req : `falcon.Request`
91
+ Request instance.
92
+ resp : `falcon.Response`
93
+ Response instance.
94
+ data_id : `str`
95
+ UUID of the SCADA data.
96
+ """
97
+ try:
98
+ if self.scada_data_mgr.validate_uuid(data_id) is False:
99
+ self.send_invalid_resource_id_error(resp)
100
+ return
101
+
102
+ sensor_config = self.load_json_data_from_request(req)
103
+ if not isinstance(sensor_config, SensorConfig):
104
+ self.send_json_parsing_error(resp)
105
+ return
106
+
107
+ self.scada_data_mgr.get(data_id).sensor_config = sensor_config
108
+ except Exception as ex:
109
+ warnings.warn(str(ex))
110
+ resp.status = falcon.HTTP_INTERNAL_SERVER_ERROR
111
+
112
+
113
+ class ScadaDataSensorFaultsHandler(ScadaDataBaseHandler):
114
+ """
115
+ Class for handling GET and POST requests concerning sensor faults in a
116
+ given SCADA data instance.
117
+ """
118
+ def on_get(self, _, resp: falcon.Response, data_id: str) -> None:
119
+ """
120
+ Gets all sensor faults of a given SCADA data instance.
121
+
122
+ Parameters
123
+ ----------
124
+ resp : `falcon.Response`
125
+ Response instance.
126
+ data_id : `str`
127
+ UUID of the SCADA data.
128
+ """
129
+ try:
130
+ if self.scada_data_mgr.validate_uuid(data_id) is False:
131
+ self.send_invalid_resource_id_error(resp)
132
+ return
133
+
134
+ sensor_faults = self.scada_data_mgr.get(data_id).sensor_faults
135
+ self.send_json_response(resp, sensor_faults)
136
+ except Exception as ex:
137
+ warnings.warn(str(ex))
138
+ resp.status = falcon.HTTP_INTERNAL_SERVER_ERROR
139
+
140
+ def on_post(self, req: falcon.Request, resp: falcon.Response, data_id: str) -> None:
141
+ """
142
+ Sets (i.e. overrides) the sensor faults in a given SCADA data instance.
143
+
144
+ Parameters
145
+ ----------
146
+ req : `falcon.Request`
147
+ Request instance.
148
+ resp : `falcon.Response`
149
+ Response instance.
150
+ data_id : `str`
151
+ UUID of the SCADA data.
152
+ """
153
+ try:
154
+ if self.scada_data_mgr.validate_uuid(data_id) is False:
155
+ self.send_invalid_resource_id_error(resp)
156
+ return
157
+
158
+ sensor_faults = self.load_json_data_from_request(req)
159
+ if not isinstance(sensor_faults, list) or \
160
+ any(not isinstance(e, SensorFault) for e in sensor_faults):
161
+ self.send_json_parsing_error(resp)
162
+ return
163
+
164
+ self.scada_data_mgr.get(data_id).sensor_faults = sensor_faults
165
+ except Exception as ex:
166
+ warnings.warn(str(ex))
167
+ resp.status = falcon.HTTP_INTERNAL_SERVER_ERROR
168
+
169
+
170
+ class ScadaDataConvertUnitsHandler(ScadaDataBaseHandler):
171
+ """
172
+ Class for handling POST requests concerning unit conversion of a
173
+ given SCADA data instance.
174
+ """
175
+ def on_post(self, req: falcon.Request, resp: falcon.Response, data_id: str) -> None:
176
+ """
177
+ Converts the units of a given SCADA data instance and returns a new SCADA data instance.
178
+
179
+ Parameters
180
+ ----------
181
+ req : `falcon.Request`
182
+ Request instance.
183
+ resp : `falcon.Response`
184
+ Response instance.
185
+ data_id : `str`
186
+ UUID of the SCADA data.
187
+ """
188
+ try:
189
+ if self.scada_data_mgr.validate_uuid(data_id) is False:
190
+ self.send_invalid_resource_id_error(resp)
191
+ return
192
+
193
+ new_units = self.load_json_data_from_request(req)
194
+ if not isinstance(new_units, dict):
195
+ self.send_json_parsing_error(resp)
196
+ return
197
+
198
+ my_scada_data = self.scada_data_mgr.get(data_id)
199
+ try:
200
+ scada_data_new = my_scada_data.convert_units(**new_units)
201
+ except Exception as ex:
202
+ self.send_error(resp, str(ex))
203
+ return
204
+
205
+ new_scada_data_id = self.scada_data_mgr.create_new_item(scada_data_new)
206
+ self.send_json_response(resp, {"data_id": new_scada_data_id})
207
+ except Exception as ex:
208
+ warnings.warn(str(ex))
209
+ resp.status = falcon.HTTP_INTERNAL_SERVER_ERROR
File without changes
@@ -0,0 +1,118 @@
1
+ """
2
+ This module provides REST API handlers for scenario events.
3
+ """
4
+ import warnings
5
+ import falcon
6
+
7
+ from .handlers import ScenarioBaseHandler
8
+ from ...simulation import Leakage, SensorFault
9
+
10
+
11
+ class ScenarioLeakageHandler(ScenarioBaseHandler):
12
+ """
13
+ Class for handling GET and POST requests concerning leakages.
14
+ """
15
+ def on_get(self, _, resp: falcon.Response, scenario_id: str) -> None:
16
+ """
17
+ Gets all leakages of a given scenario.
18
+
19
+ Parameters
20
+ ----------
21
+ resp : `falcon.Response`
22
+ Response instance.
23
+ scenario_id : `str`
24
+ UUID of the scenario.
25
+ """
26
+ try:
27
+ if self.scenario_mgr.validate_uuid(scenario_id) is False:
28
+ self.send_invalid_resource_id_error(resp)
29
+ return
30
+
31
+ my_leakages = self.scenario_mgr.get(scenario_id).leakages
32
+ self.send_json_response(resp, my_leakages)
33
+ except Exception as ex:
34
+ warnings.warn(str(ex))
35
+ resp.status = falcon.HTTP_INTERNAL_SERVER_ERROR
36
+
37
+ def on_post(self, req: falcon.Request, resp: falcon.Response, scenario_id: str) -> None:
38
+ """
39
+ Adds a new leakage to a given scenario.
40
+
41
+ Parameters
42
+ ----------
43
+ req : `falcon.Request`
44
+ Request instance.
45
+ resp : `falcon.Response`
46
+ Response instance.
47
+ scenario_id : `str`
48
+ UUID of the scenario.
49
+ """
50
+ try:
51
+ if self.scenario_mgr.validate_uuid(scenario_id) is False:
52
+ self.send_invalid_resource_id_error(resp)
53
+ return
54
+
55
+ leakage = self.load_json_data_from_request(req)
56
+ if not isinstance(leakage, Leakage):
57
+ self.send_json_parsing_error(resp)
58
+ return
59
+
60
+ self.scenario_mgr.get(scenario_id).add_leakage(leakage)
61
+ except Exception as ex:
62
+ warnings.warn(str(ex))
63
+ resp.status = falcon.HTTP_INTERNAL_SERVER_ERROR
64
+
65
+
66
+ class ScenarioSensorFaultHandler(ScenarioBaseHandler):
67
+ """
68
+ Class for handling GET and POST requests concerning sensor faults.
69
+ """
70
+ def on_get(self, _, resp: falcon.Response, scenario_id: str) -> None:
71
+ """
72
+ Gets all sensor faults of a given scenario.
73
+
74
+ Parameters
75
+ ----------
76
+ resp : `falcon.Response`
77
+ Response instance.
78
+ scenario_id : `str`
79
+ UUID of the scenario.
80
+ """
81
+ try:
82
+ if self.scenario_mgr.validate_uuid(scenario_id) is False:
83
+ self.send_invalid_resource_id_error(resp)
84
+ return
85
+
86
+ my_sensor_faults = self.scenario_mgr.get(scenario_id).sensor_faults
87
+ self.send_json_response(resp, my_sensor_faults)
88
+ except Exception as ex:
89
+ warnings.warn(str(ex))
90
+ resp.status = falcon.HTTP_INTERNAL_SERVER_ERROR
91
+
92
+ def on_post(self, req: falcon.Request, resp: falcon.Response, scenario_id: str) -> None:
93
+ """
94
+ Adds a new sensor fault to a given scenario.
95
+
96
+ Parameters
97
+ ----------
98
+ req : `falcon.Request`
99
+ Request instance.
100
+ resp : `falcon.Response`
101
+ Response instance.
102
+ scenario_id : `str`
103
+ UUID of the scenario.
104
+ """
105
+ try:
106
+ if self.scenario_mgr.validate_uuid(scenario_id) is False:
107
+ self.send_invalid_resource_id_error(resp)
108
+ return
109
+
110
+ sensor_fault = self.load_json_data_from_request(req)
111
+ if not isinstance(sensor_fault, SensorFault):
112
+ self.send_json_parsing_error(resp)
113
+ return
114
+
115
+ self.scenario_mgr.get(scenario_id).add_sensor_fault(sensor_fault)
116
+ except Exception as ex:
117
+ warnings.warn(str(ex))
118
+ resp.status = falcon.HTTP_INTERNAL_SERVER_ERROR