epyt-flow 0.1.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.
- epyt_flow/EPANET/EPANET/SRC_engines/AUTHORS +28 -0
- epyt_flow/EPANET/EPANET/SRC_engines/LICENSE +21 -0
- epyt_flow/EPANET/EPANET/SRC_engines/Readme_SRC_Engines.txt +18 -0
- epyt_flow/EPANET/EPANET/SRC_engines/enumstxt.h +134 -0
- epyt_flow/EPANET/EPANET/SRC_engines/epanet.c +5578 -0
- epyt_flow/EPANET/EPANET/SRC_engines/epanet2.c +865 -0
- epyt_flow/EPANET/EPANET/SRC_engines/epanet2.def +131 -0
- epyt_flow/EPANET/EPANET/SRC_engines/errors.dat +73 -0
- epyt_flow/EPANET/EPANET/SRC_engines/funcs.h +193 -0
- epyt_flow/EPANET/EPANET/SRC_engines/genmmd.c +1000 -0
- epyt_flow/EPANET/EPANET/SRC_engines/hash.c +177 -0
- epyt_flow/EPANET/EPANET/SRC_engines/hash.h +28 -0
- epyt_flow/EPANET/EPANET/SRC_engines/hydcoeffs.c +1151 -0
- epyt_flow/EPANET/EPANET/SRC_engines/hydraul.c +1117 -0
- epyt_flow/EPANET/EPANET/SRC_engines/hydsolver.c +720 -0
- epyt_flow/EPANET/EPANET/SRC_engines/hydstatus.c +476 -0
- epyt_flow/EPANET/EPANET/SRC_engines/include/epanet2.h +431 -0
- epyt_flow/EPANET/EPANET/SRC_engines/include/epanet2_2.h +1786 -0
- epyt_flow/EPANET/EPANET/SRC_engines/include/epanet2_enums.h +468 -0
- epyt_flow/EPANET/EPANET/SRC_engines/inpfile.c +810 -0
- epyt_flow/EPANET/EPANET/SRC_engines/input1.c +707 -0
- epyt_flow/EPANET/EPANET/SRC_engines/input2.c +864 -0
- epyt_flow/EPANET/EPANET/SRC_engines/input3.c +2170 -0
- epyt_flow/EPANET/EPANET/SRC_engines/main.c +93 -0
- epyt_flow/EPANET/EPANET/SRC_engines/mempool.c +142 -0
- epyt_flow/EPANET/EPANET/SRC_engines/mempool.h +24 -0
- epyt_flow/EPANET/EPANET/SRC_engines/output.c +852 -0
- epyt_flow/EPANET/EPANET/SRC_engines/project.c +1359 -0
- epyt_flow/EPANET/EPANET/SRC_engines/quality.c +685 -0
- epyt_flow/EPANET/EPANET/SRC_engines/qualreact.c +743 -0
- epyt_flow/EPANET/EPANET/SRC_engines/qualroute.c +694 -0
- epyt_flow/EPANET/EPANET/SRC_engines/report.c +1489 -0
- epyt_flow/EPANET/EPANET/SRC_engines/rules.c +1362 -0
- epyt_flow/EPANET/EPANET/SRC_engines/smatrix.c +871 -0
- epyt_flow/EPANET/EPANET/SRC_engines/text.h +497 -0
- epyt_flow/EPANET/EPANET/SRC_engines/types.h +874 -0
- epyt_flow/EPANET/EPANET-MSX/MSX_Updates.txt +53 -0
- epyt_flow/EPANET/EPANET-MSX/Src/dispersion.h +27 -0
- epyt_flow/EPANET/EPANET-MSX/Src/hash.c +107 -0
- epyt_flow/EPANET/EPANET-MSX/Src/hash.h +28 -0
- epyt_flow/EPANET/EPANET-MSX/Src/include/epanetmsx.h +102 -0
- epyt_flow/EPANET/EPANET-MSX/Src/include/epanetmsx_export.h +42 -0
- epyt_flow/EPANET/EPANET-MSX/Src/mathexpr.c +937 -0
- epyt_flow/EPANET/EPANET-MSX/Src/mathexpr.h +39 -0
- epyt_flow/EPANET/EPANET-MSX/Src/mempool.c +204 -0
- epyt_flow/EPANET/EPANET-MSX/Src/mempool.h +24 -0
- epyt_flow/EPANET/EPANET-MSX/Src/msxchem.c +1285 -0
- epyt_flow/EPANET/EPANET-MSX/Src/msxcompiler.c +368 -0
- epyt_flow/EPANET/EPANET-MSX/Src/msxdict.h +42 -0
- epyt_flow/EPANET/EPANET-MSX/Src/msxdispersion.c +586 -0
- epyt_flow/EPANET/EPANET-MSX/Src/msxerr.c +116 -0
- epyt_flow/EPANET/EPANET-MSX/Src/msxfile.c +260 -0
- epyt_flow/EPANET/EPANET-MSX/Src/msxfuncs.c +175 -0
- epyt_flow/EPANET/EPANET-MSX/Src/msxfuncs.h +35 -0
- epyt_flow/EPANET/EPANET-MSX/Src/msxinp.c +1504 -0
- epyt_flow/EPANET/EPANET-MSX/Src/msxout.c +401 -0
- epyt_flow/EPANET/EPANET-MSX/Src/msxproj.c +791 -0
- epyt_flow/EPANET/EPANET-MSX/Src/msxqual.c +2010 -0
- epyt_flow/EPANET/EPANET-MSX/Src/msxrpt.c +400 -0
- epyt_flow/EPANET/EPANET-MSX/Src/msxtank.c +422 -0
- epyt_flow/EPANET/EPANET-MSX/Src/msxtoolkit.c +1164 -0
- epyt_flow/EPANET/EPANET-MSX/Src/msxtypes.h +551 -0
- epyt_flow/EPANET/EPANET-MSX/Src/msxutils.c +524 -0
- epyt_flow/EPANET/EPANET-MSX/Src/msxutils.h +56 -0
- epyt_flow/EPANET/EPANET-MSX/Src/newton.c +158 -0
- epyt_flow/EPANET/EPANET-MSX/Src/newton.h +34 -0
- epyt_flow/EPANET/EPANET-MSX/Src/rk5.c +287 -0
- epyt_flow/EPANET/EPANET-MSX/Src/rk5.h +39 -0
- epyt_flow/EPANET/EPANET-MSX/Src/ros2.c +293 -0
- epyt_flow/EPANET/EPANET-MSX/Src/ros2.h +35 -0
- epyt_flow/EPANET/EPANET-MSX/Src/smatrix.c +816 -0
- epyt_flow/EPANET/EPANET-MSX/Src/smatrix.h +29 -0
- epyt_flow/EPANET/EPANET-MSX/readme.txt +14 -0
- epyt_flow/EPANET/compile.sh +4 -0
- epyt_flow/VERSION +1 -0
- epyt_flow/__init__.py +24 -0
- epyt_flow/data/__init__.py +0 -0
- epyt_flow/data/benchmarks/__init__.py +11 -0
- epyt_flow/data/benchmarks/batadal.py +257 -0
- epyt_flow/data/benchmarks/batadal_data.py +28 -0
- epyt_flow/data/benchmarks/battledim.py +473 -0
- epyt_flow/data/benchmarks/battledim_data.py +51 -0
- epyt_flow/data/benchmarks/gecco_water_quality.py +267 -0
- epyt_flow/data/benchmarks/leakdb.py +592 -0
- epyt_flow/data/benchmarks/leakdb_data.py +18923 -0
- epyt_flow/data/benchmarks/water_usage.py +123 -0
- epyt_flow/data/networks.py +650 -0
- epyt_flow/gym/__init__.py +4 -0
- epyt_flow/gym/control_gyms.py +47 -0
- epyt_flow/gym/scenario_control_env.py +101 -0
- epyt_flow/metrics.py +404 -0
- epyt_flow/models/__init__.py +2 -0
- epyt_flow/models/event_detector.py +31 -0
- epyt_flow/models/sensor_interpolation_detector.py +118 -0
- epyt_flow/rest_api/__init__.py +4 -0
- epyt_flow/rest_api/base_handler.py +70 -0
- epyt_flow/rest_api/res_manager.py +95 -0
- epyt_flow/rest_api/scada_data_handler.py +476 -0
- epyt_flow/rest_api/scenario_handler.py +352 -0
- epyt_flow/rest_api/server.py +106 -0
- epyt_flow/serialization.py +438 -0
- epyt_flow/simulation/__init__.py +5 -0
- epyt_flow/simulation/events/__init__.py +6 -0
- epyt_flow/simulation/events/actuator_events.py +259 -0
- epyt_flow/simulation/events/event.py +81 -0
- epyt_flow/simulation/events/leakages.py +404 -0
- epyt_flow/simulation/events/sensor_faults.py +267 -0
- epyt_flow/simulation/events/sensor_reading_attack.py +185 -0
- epyt_flow/simulation/events/sensor_reading_event.py +170 -0
- epyt_flow/simulation/events/system_event.py +88 -0
- epyt_flow/simulation/parallel_simulation.py +147 -0
- epyt_flow/simulation/scada/__init__.py +3 -0
- epyt_flow/simulation/scada/advanced_control.py +134 -0
- epyt_flow/simulation/scada/scada_data.py +1589 -0
- epyt_flow/simulation/scada/scada_data_export.py +255 -0
- epyt_flow/simulation/scenario_config.py +608 -0
- epyt_flow/simulation/scenario_simulator.py +1897 -0
- epyt_flow/simulation/scenario_visualizer.py +61 -0
- epyt_flow/simulation/sensor_config.py +1289 -0
- epyt_flow/topology.py +290 -0
- epyt_flow/uncertainty/__init__.py +3 -0
- epyt_flow/uncertainty/model_uncertainty.py +302 -0
- epyt_flow/uncertainty/sensor_noise.py +73 -0
- epyt_flow/uncertainty/uncertainties.py +555 -0
- epyt_flow/uncertainty/utils.py +206 -0
- epyt_flow/utils.py +306 -0
- epyt_flow-0.1.0.dist-info/LICENSE +21 -0
- epyt_flow-0.1.0.dist-info/METADATA +139 -0
- epyt_flow-0.1.0.dist-info/RECORD +131 -0
- epyt_flow-0.1.0.dist-info/WHEEL +5 -0
- epyt_flow-0.1.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,352 @@
|
|
|
1
|
+
"""
|
|
2
|
+
This module provides all handlers for requests concerning scenarios.
|
|
3
|
+
"""
|
|
4
|
+
import warnings
|
|
5
|
+
import falcon
|
|
6
|
+
|
|
7
|
+
from .base_handler import BaseHandler
|
|
8
|
+
from .res_manager import ResourceManager
|
|
9
|
+
from .scada_data_handler import ScadaDataManager
|
|
10
|
+
from ..simulation import ScenarioSimulator, Leakage, SensorConfig
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class ScenarioManager(ResourceManager):
|
|
14
|
+
"""
|
|
15
|
+
Class for managing all scenarios that are currently used by the REST API.
|
|
16
|
+
"""
|
|
17
|
+
def create(self, **kwds) -> str:
|
|
18
|
+
"""
|
|
19
|
+
Creates a new scenario -- e.g. loading a given .inp file or
|
|
20
|
+
using a given scenario configuration.
|
|
21
|
+
|
|
22
|
+
Returns
|
|
23
|
+
-------
|
|
24
|
+
`str`
|
|
25
|
+
UUID of the new scenario.
|
|
26
|
+
"""
|
|
27
|
+
return self.create_new_item(ScenarioSimulator(**kwds))
|
|
28
|
+
|
|
29
|
+
def close_item(self, item: ScenarioSimulator) -> None:
|
|
30
|
+
item.close()
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
class ScenarioBaseHandler(BaseHandler):
|
|
34
|
+
"""
|
|
35
|
+
Base class for all handlers concerning scenarios.
|
|
36
|
+
|
|
37
|
+
Parameters
|
|
38
|
+
----------
|
|
39
|
+
scenario_mgr : :class:`~epyt_flow.rest_api.scenario_handler.ScenarioManager`
|
|
40
|
+
Instance for managing all scenarios.
|
|
41
|
+
"""
|
|
42
|
+
def __init__(self, scenario_mgr: ScenarioManager):
|
|
43
|
+
self.scenario_mgr = scenario_mgr
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
class ScenarioRemoveHandler(ScenarioBaseHandler):
|
|
47
|
+
"""
|
|
48
|
+
Class for handling a DELETE request for a given scenario.
|
|
49
|
+
"""
|
|
50
|
+
def on_delete(self, _, resp: falcon.Response, scenario_id: str) -> None:
|
|
51
|
+
"""
|
|
52
|
+
Deletes a given scenario.
|
|
53
|
+
|
|
54
|
+
Parameters
|
|
55
|
+
----------
|
|
56
|
+
resp : `falcon.Response`
|
|
57
|
+
Response instance.
|
|
58
|
+
scenario_id : `str`
|
|
59
|
+
UUID of the scenario.
|
|
60
|
+
"""
|
|
61
|
+
try:
|
|
62
|
+
if self.scenario_mgr.validate_uuid(scenario_id) is False:
|
|
63
|
+
self.send_invalid_resource_id_error(resp)
|
|
64
|
+
return
|
|
65
|
+
|
|
66
|
+
self.scenario_mgr.remove(scenario_id)
|
|
67
|
+
except Exception as ex:
|
|
68
|
+
warnings.warn(str(ex))
|
|
69
|
+
resp.status = falcon.HTTP_INTERNAL_SERVER_ERROR
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
class ScenarioConfigHandler(ScenarioBaseHandler):
|
|
73
|
+
"""
|
|
74
|
+
Class for handling a GET request for getting the scenario configuration of a given scenario.
|
|
75
|
+
"""
|
|
76
|
+
def on_get(self, _, resp: falcon.Response, scenario_id: str) -> None:
|
|
77
|
+
"""
|
|
78
|
+
Gets the scenario configuration of a given scenario.
|
|
79
|
+
|
|
80
|
+
Parameters
|
|
81
|
+
----------
|
|
82
|
+
resp : `falcon.Response`
|
|
83
|
+
Response instance.
|
|
84
|
+
scenario_id : `str`
|
|
85
|
+
UUID of the scenario.
|
|
86
|
+
"""
|
|
87
|
+
try:
|
|
88
|
+
if self.scenario_mgr.validate_uuid(scenario_id) is False:
|
|
89
|
+
self.send_invalid_resource_id_error(resp)
|
|
90
|
+
return
|
|
91
|
+
|
|
92
|
+
my_sceanrio_config = self.scenario_mgr.get(scenario_id).get_scenario_config()
|
|
93
|
+
self.send_json_response(resp, my_sceanrio_config)
|
|
94
|
+
except Exception as ex:
|
|
95
|
+
warnings.warn(str(ex))
|
|
96
|
+
resp.status = falcon.HTTP_INTERNAL_SERVER_ERROR
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
class ScenarioNewHandler(ScenarioBaseHandler):
|
|
100
|
+
"""
|
|
101
|
+
Class for handling POST requests for creating a new scenario.
|
|
102
|
+
"""
|
|
103
|
+
def on_post(self, req: falcon.Request, resp: falcon.Response) -> None:
|
|
104
|
+
"""
|
|
105
|
+
Creates/Loads a new scenario.
|
|
106
|
+
|
|
107
|
+
Parameters
|
|
108
|
+
----------
|
|
109
|
+
req : `falcon.Request`
|
|
110
|
+
Request instance.
|
|
111
|
+
resp : `falcon.Response`
|
|
112
|
+
Response instance.
|
|
113
|
+
scenario_id : `str`
|
|
114
|
+
UUID of the scenario.
|
|
115
|
+
"""
|
|
116
|
+
try:
|
|
117
|
+
args = self.load_json_data_from_request(req)
|
|
118
|
+
scenario_id = self.scenario_mgr.create(**args)
|
|
119
|
+
self.send_json_response(resp, {"scenario_id": scenario_id})
|
|
120
|
+
except Exception as ex:
|
|
121
|
+
warnings.warn(str(ex))
|
|
122
|
+
resp.status = falcon.HTTP_INTERNAL_SERVER_ERROR
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
class ScenarioLeakageHandler(ScenarioBaseHandler):
|
|
126
|
+
"""
|
|
127
|
+
Class for handling GET and POST requests concerning leakages.
|
|
128
|
+
"""
|
|
129
|
+
def on_get(self, _, resp: falcon.Response, scenario_id: str) -> None:
|
|
130
|
+
"""
|
|
131
|
+
Gets all leakages of a given scenario.
|
|
132
|
+
|
|
133
|
+
Parameters
|
|
134
|
+
----------
|
|
135
|
+
resp : `falcon.Response`
|
|
136
|
+
Response instance.
|
|
137
|
+
scenario_id : `str`
|
|
138
|
+
UUID of the scenario.
|
|
139
|
+
"""
|
|
140
|
+
try:
|
|
141
|
+
if self.scenario_mgr.validate_uuid(scenario_id) is False:
|
|
142
|
+
self.send_invalid_resource_id_error(resp)
|
|
143
|
+
return
|
|
144
|
+
|
|
145
|
+
my_leakages = self.scenario_mgr.get(scenario_id).leakages
|
|
146
|
+
self.send_json_response(resp, my_leakages)
|
|
147
|
+
except Exception as ex:
|
|
148
|
+
warnings.warn(str(ex))
|
|
149
|
+
resp.status = falcon.HTTP_INTERNAL_SERVER_ERROR
|
|
150
|
+
|
|
151
|
+
def on_post(self, req: falcon.Request, resp: falcon.Response, scenario_id: str) -> None:
|
|
152
|
+
"""
|
|
153
|
+
Adds a new leakage to a given scenario.
|
|
154
|
+
|
|
155
|
+
Parameters
|
|
156
|
+
----------
|
|
157
|
+
req : `falcon.Request`
|
|
158
|
+
Request instance.
|
|
159
|
+
resp : `falcon.Response`
|
|
160
|
+
Response instance.
|
|
161
|
+
scenario_id : `str`
|
|
162
|
+
UUID of the scenario.
|
|
163
|
+
"""
|
|
164
|
+
try:
|
|
165
|
+
if self.scenario_mgr.validate_uuid(scenario_id) is False:
|
|
166
|
+
self.send_invalid_resource_id_error(resp)
|
|
167
|
+
return
|
|
168
|
+
|
|
169
|
+
leakage = self.load_json_data_from_request(req)
|
|
170
|
+
if not isinstance(leakage, Leakage):
|
|
171
|
+
self.send_json_parsing_error(resp)
|
|
172
|
+
return
|
|
173
|
+
|
|
174
|
+
self.scenario_mgr.get(scenario_id).add_leakage(leakage)
|
|
175
|
+
except Exception as ex:
|
|
176
|
+
warnings.warn(str(ex))
|
|
177
|
+
resp.status = falcon.HTTP_INTERNAL_SERVER_ERROR
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
class ScenarioTopologyHandler(ScenarioBaseHandler):
|
|
181
|
+
"""
|
|
182
|
+
Class for handling GET requests for getting the topology of a given scenario.
|
|
183
|
+
"""
|
|
184
|
+
def on_get(self, _, resp: falcon.Response, scenario_id: str) -> None:
|
|
185
|
+
"""
|
|
186
|
+
Gets the topology of a given scenario.
|
|
187
|
+
|
|
188
|
+
Parameters
|
|
189
|
+
----------
|
|
190
|
+
resp : `falcon.Response`
|
|
191
|
+
Response instance.
|
|
192
|
+
scenario_id : `str`
|
|
193
|
+
UUID of the scenario.
|
|
194
|
+
"""
|
|
195
|
+
try:
|
|
196
|
+
if self.scenario_mgr.validate_uuid(scenario_id) is False:
|
|
197
|
+
self.send_invalid_resource_id_error(resp)
|
|
198
|
+
return
|
|
199
|
+
|
|
200
|
+
my_topology = self.scenario_mgr.get(scenario_id).get_topology()
|
|
201
|
+
self.send_json_response(resp, my_topology)
|
|
202
|
+
except Exception as ex:
|
|
203
|
+
warnings.warn(str(ex))
|
|
204
|
+
resp.status = falcon.HTTP_INTERNAL_SERVER_ERROR
|
|
205
|
+
|
|
206
|
+
|
|
207
|
+
class ScenarioGeneralParamsHandler(ScenarioBaseHandler):
|
|
208
|
+
"""
|
|
209
|
+
Class for handling GET and POST requests for the general parameters of a given scenario.
|
|
210
|
+
"""
|
|
211
|
+
def on_get(self, _, resp: falcon.Response, scenario_id: str) -> None:
|
|
212
|
+
"""
|
|
213
|
+
Gets the general parameters (e.g. simulation duration, etc.) of a given scenario.
|
|
214
|
+
|
|
215
|
+
Parameters
|
|
216
|
+
----------
|
|
217
|
+
resp : `falcon.Response`
|
|
218
|
+
Response instance.
|
|
219
|
+
scenario_id : `str`
|
|
220
|
+
UUID of the scenario.
|
|
221
|
+
"""
|
|
222
|
+
try:
|
|
223
|
+
if self.scenario_mgr.validate_uuid(scenario_id) is False:
|
|
224
|
+
self.send_invalid_resource_id_error(resp)
|
|
225
|
+
return
|
|
226
|
+
|
|
227
|
+
my_general_params = self.scenario_mgr.get(scenario_id).get_scenario_config().\
|
|
228
|
+
general_params
|
|
229
|
+
self.send_json_response(resp, my_general_params)
|
|
230
|
+
except Exception as ex:
|
|
231
|
+
warnings.warn(str(ex))
|
|
232
|
+
resp.status = falcon.HTTP_INTERNAL_SERVER_ERROR
|
|
233
|
+
|
|
234
|
+
def on_post(self, req: falcon.Request, resp: falcon.Response, scenario_id: str) -> None:
|
|
235
|
+
"""
|
|
236
|
+
Sets the general parameters of a given scenario.
|
|
237
|
+
|
|
238
|
+
Parameters
|
|
239
|
+
----------
|
|
240
|
+
resp : `falcon.Request`
|
|
241
|
+
Request instance.
|
|
242
|
+
scenario_id : `str`
|
|
243
|
+
UUID of the scenario.
|
|
244
|
+
"""
|
|
245
|
+
try:
|
|
246
|
+
if self.scenario_mgr.validate_uuid(scenario_id) is False:
|
|
247
|
+
self.send_invalid_resource_id_error(resp)
|
|
248
|
+
return
|
|
249
|
+
|
|
250
|
+
general_params = self.load_json_data_from_request(req)
|
|
251
|
+
if not isinstance(general_params, dict):
|
|
252
|
+
self.send_json_parsing_error(resp)
|
|
253
|
+
return
|
|
254
|
+
|
|
255
|
+
self.scenario_mgr.get(scenario_id).set_general_parameters(**general_params)
|
|
256
|
+
except Exception as ex:
|
|
257
|
+
warnings.warn(str(ex))
|
|
258
|
+
resp.status = falcon.HTTP_INTERNAL_SERVER_ERROR
|
|
259
|
+
|
|
260
|
+
|
|
261
|
+
class ScenarioSensorConfigHandler(ScenarioBaseHandler):
|
|
262
|
+
"""
|
|
263
|
+
Class for handling GET and POST requests for the sensor configuration of a given scenario.
|
|
264
|
+
"""
|
|
265
|
+
def on_get(self, _, resp: falcon.Response, scenario_id: str) -> None:
|
|
266
|
+
"""
|
|
267
|
+
Gets the sensor configuration of a given scenario.
|
|
268
|
+
|
|
269
|
+
Parameters
|
|
270
|
+
----------
|
|
271
|
+
resp : `falcon.Response`
|
|
272
|
+
Response instance.
|
|
273
|
+
scenario_id : `str`
|
|
274
|
+
UUID of the scenario.
|
|
275
|
+
"""
|
|
276
|
+
try:
|
|
277
|
+
if self.scenario_mgr.validate_uuid(scenario_id) is False:
|
|
278
|
+
self.send_invalid_resource_id_error(resp)
|
|
279
|
+
return
|
|
280
|
+
|
|
281
|
+
my_sensor_config = self.scenario_mgr.get(scenario_id).sensor_config
|
|
282
|
+
self.send_json_response(resp, my_sensor_config)
|
|
283
|
+
except Exception as ex:
|
|
284
|
+
warnings.warn(str(ex))
|
|
285
|
+
resp.status = falcon.HTTP_INTERNAL_SERVER_ERROR
|
|
286
|
+
|
|
287
|
+
def on_post(self, req: falcon.Request, resp: falcon.Response, scenario_id: str) -> None:
|
|
288
|
+
"""
|
|
289
|
+
Sets the sensor configuration of a given scenario.
|
|
290
|
+
|
|
291
|
+
Parameters
|
|
292
|
+
----------
|
|
293
|
+
resp : `falcon.Request`
|
|
294
|
+
Request instance.
|
|
295
|
+
scenario_id : `str`
|
|
296
|
+
UUID of the scenario.
|
|
297
|
+
"""
|
|
298
|
+
try:
|
|
299
|
+
if self.scenario_mgr.validate_uuid(scenario_id) is False:
|
|
300
|
+
self.send_invalid_resource_id_error(resp)
|
|
301
|
+
return
|
|
302
|
+
|
|
303
|
+
sensor_config = self.load_json_data_from_request(req)
|
|
304
|
+
if not isinstance(sensor_config, SensorConfig):
|
|
305
|
+
self.send_json_parsing_error(resp)
|
|
306
|
+
return
|
|
307
|
+
|
|
308
|
+
my_scenario = self.scenario_mgr.get(scenario_id)
|
|
309
|
+
my_scenario.sensor_config = sensor_config
|
|
310
|
+
except Exception as ex:
|
|
311
|
+
warnings.warn(str(ex))
|
|
312
|
+
resp.status = falcon.HTTP_INTERNAL_SERVER_ERROR
|
|
313
|
+
|
|
314
|
+
|
|
315
|
+
class ScenarioSimulationHandler(ScenarioBaseHandler):
|
|
316
|
+
"""
|
|
317
|
+
Class for handling GET requests for simulating a given scenario.
|
|
318
|
+
|
|
319
|
+
Parameters
|
|
320
|
+
----------
|
|
321
|
+
scada_data_mgr : :class:`~epyt_flow.rest_api.scenario_handler.ScadaDataBaseHandler`
|
|
322
|
+
SCADA data manager.
|
|
323
|
+
"""
|
|
324
|
+
def __init__(self, scada_data_mgr: ScadaDataManager, **kwds):
|
|
325
|
+
self.scada_data_mgr = scada_data_mgr
|
|
326
|
+
|
|
327
|
+
super().__init__(**kwds)
|
|
328
|
+
|
|
329
|
+
def on_get(self, _, resp: falcon.Response, scenario_id: str) -> None:
|
|
330
|
+
"""
|
|
331
|
+
Runs the simulation of a given scenario.
|
|
332
|
+
|
|
333
|
+
Parameters
|
|
334
|
+
----------
|
|
335
|
+
resp : `falcon.Response`
|
|
336
|
+
Response instance.
|
|
337
|
+
scenario_id : `str`
|
|
338
|
+
UUID of the scenario.
|
|
339
|
+
"""
|
|
340
|
+
try:
|
|
341
|
+
if self.scenario_mgr.validate_uuid(scenario_id) is False:
|
|
342
|
+
self.send_invalid_resource_id_error(resp)
|
|
343
|
+
return
|
|
344
|
+
|
|
345
|
+
my_scenario = self.scenario_mgr.get(scenario_id)
|
|
346
|
+
res = my_scenario.run_simulation()
|
|
347
|
+
|
|
348
|
+
data_id = self.scada_data_mgr.create_new_item(res)
|
|
349
|
+
self.send_json_response(resp, {"data_id": data_id})
|
|
350
|
+
except Exception as ex:
|
|
351
|
+
warnings.warn(str(ex))
|
|
352
|
+
resp.status = falcon.HTTP_INTERNAL_SERVER_ERROR
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
"""
|
|
2
|
+
This module provides the EPyT-Flow REST API server.
|
|
3
|
+
"""
|
|
4
|
+
from wsgiref.simple_server import make_server, WSGIServer
|
|
5
|
+
import falcon
|
|
6
|
+
|
|
7
|
+
from .scenario_handler import ScenarioManager, ScenarioNewHandler, ScenarioRemoveHandler, \
|
|
8
|
+
ScenarioGeneralParamsHandler, ScenarioSensorConfigHandler, ScenarioSimulationHandler, \
|
|
9
|
+
ScenarioTopologyHandler, ScenarioConfigHandler, ScenarioLeakageHandler
|
|
10
|
+
from .scada_data_handler import ScadaDataManager, ScadaDataSensorConfigHandler, \
|
|
11
|
+
ScadaDataPressuresHandler, ScadaDataDemandsHandler, ScadaDataFlowsHandler, \
|
|
12
|
+
ScadaDataLinksQualityHandler, ScadaDataNodesQualityHandler, ScadaDataRemoveHandler, \
|
|
13
|
+
ScadaDataSensorFaultsHandler, ScadaDataNodeBulkSpeciesHandler, \
|
|
14
|
+
ScadaDataLinkBulkSpeciesHandler, ScadaDataSurfaceSpeciesHandler, ScadaDataTankVolumesHandler, \
|
|
15
|
+
ScadaDataPumpStatesHandler, ScadaDataValveStatesHandler
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class RestApiService():
|
|
19
|
+
"""
|
|
20
|
+
Class implementing the REST API server.
|
|
21
|
+
|
|
22
|
+
Parameters
|
|
23
|
+
----------
|
|
24
|
+
port : `int`, optional
|
|
25
|
+
Port of the server.
|
|
26
|
+
|
|
27
|
+
The default is 8080
|
|
28
|
+
"""
|
|
29
|
+
def __init__(self, port: int = 8080):
|
|
30
|
+
self.app = falcon.App()
|
|
31
|
+
self.__port = port
|
|
32
|
+
|
|
33
|
+
self.scenario_mgr = ScenarioManager()
|
|
34
|
+
self.scada_data_mgr = ScadaDataManager()
|
|
35
|
+
|
|
36
|
+
self.app.add_route("/scenario/new",
|
|
37
|
+
ScenarioNewHandler(self.scenario_mgr))
|
|
38
|
+
self.app.add_route("/scenario/{scenario_id}",
|
|
39
|
+
ScenarioRemoveHandler(self.scenario_mgr))
|
|
40
|
+
self.app.add_route("/scenario/{scenario_id}/topology",
|
|
41
|
+
ScenarioTopologyHandler(self.scenario_mgr))
|
|
42
|
+
self.app.add_route("/scenario/{scenario_id}/scenario_config",
|
|
43
|
+
ScenarioConfigHandler(self.scenario_mgr))
|
|
44
|
+
self.app.add_route("/scenario/{scenario_id}/general_params",
|
|
45
|
+
ScenarioGeneralParamsHandler(self.scenario_mgr))
|
|
46
|
+
self.app.add_route("/scenario/{scenario_id}/sensor_config",
|
|
47
|
+
ScenarioSensorConfigHandler(self.scenario_mgr))
|
|
48
|
+
self.app.add_route("/scenario/{scenario_id}/leakages",
|
|
49
|
+
ScenarioLeakageHandler(self.scenario_mgr))
|
|
50
|
+
self.app.add_route("/scenario/{scenario_id}/simulation",
|
|
51
|
+
ScenarioSimulationHandler(scenario_mgr=self.scenario_mgr,
|
|
52
|
+
scada_data_mgr=self.scada_data_mgr))
|
|
53
|
+
|
|
54
|
+
self.app.add_route("/scada_data/{data_id}",
|
|
55
|
+
ScadaDataRemoveHandler(self.scada_data_mgr))
|
|
56
|
+
self.app.add_route("/scada_data/{data_id}/sensor_config",
|
|
57
|
+
ScadaDataSensorConfigHandler(self.scada_data_mgr))
|
|
58
|
+
self.app.add_route("/scada_data/{data_id}/sensor_faults",
|
|
59
|
+
ScadaDataSensorFaultsHandler(self.scada_data_mgr))
|
|
60
|
+
self.app.add_route("/scada_data/{data_id}/pressures",
|
|
61
|
+
ScadaDataPressuresHandler(self.scada_data_mgr))
|
|
62
|
+
self.app.add_route("/scada_data/{data_id}/flows",
|
|
63
|
+
ScadaDataFlowsHandler(self.scada_data_mgr))
|
|
64
|
+
self.app.add_route("/scada_data/{data_id}/demands",
|
|
65
|
+
ScadaDataDemandsHandler(self.scada_data_mgr))
|
|
66
|
+
self.app.add_route("/scada_data/{data_id}/pump_states",
|
|
67
|
+
ScadaDataPumpStatesHandler(self.scada_data_mgr))
|
|
68
|
+
self.app.add_route("/scada_data/{data_id}/valve_states",
|
|
69
|
+
ScadaDataValveStatesHandler(self.scada_data_mgr))
|
|
70
|
+
self.app.add_route("/scada_data/{data_id}/tank_volumes",
|
|
71
|
+
ScadaDataTankVolumesHandler(self.scada_data_mgr))
|
|
72
|
+
self.app.add_route("/scada_data/{data_id}/node_qualities",
|
|
73
|
+
ScadaDataNodesQualityHandler(self.scada_data_mgr))
|
|
74
|
+
self.app.add_route("/scada_data/{data_id}/link_qualities",
|
|
75
|
+
ScadaDataLinksQualityHandler(self.scada_data_mgr))
|
|
76
|
+
self.app.add_route("/scada_data/{data_id}/node_bulk_species",
|
|
77
|
+
ScadaDataNodeBulkSpeciesHandler(self.scada_data_mgr))
|
|
78
|
+
self.app.add_route("/scada_data/{data_id}/link_bulk_species",
|
|
79
|
+
ScadaDataLinkBulkSpeciesHandler(self.scada_data_mgr))
|
|
80
|
+
self.app.add_route("/scada_data/{data_id}/surface_species",
|
|
81
|
+
ScadaDataSurfaceSpeciesHandler(self.scada_data_mgr))
|
|
82
|
+
|
|
83
|
+
@property
|
|
84
|
+
def port(self) -> int:
|
|
85
|
+
"""
|
|
86
|
+
Gets the port of the web server.
|
|
87
|
+
|
|
88
|
+
Returns
|
|
89
|
+
-------
|
|
90
|
+
`int`
|
|
91
|
+
Port.
|
|
92
|
+
"""
|
|
93
|
+
return self.__port
|
|
94
|
+
|
|
95
|
+
def make_server(self) -> WSGIServer:
|
|
96
|
+
"""
|
|
97
|
+
Returns a new web server.
|
|
98
|
+
"""
|
|
99
|
+
return make_server("", self.__port, self.app)
|
|
100
|
+
|
|
101
|
+
def run(self) -> None:
|
|
102
|
+
"""
|
|
103
|
+
Runs the REST service.
|
|
104
|
+
"""
|
|
105
|
+
with self.make_server() as httpd:
|
|
106
|
+
httpd.serve_forever()
|