1"""
2The module provides REST API handlers for some SCADA data requests.
3"""
4import warnings
5import falcon
6
7from ..base_handler import BaseHandler
8from ..res_manager import ResourceManager
9from ...simulation import SensorConfig, SensorFault
10
11
[docs]
12class ScadaDataManager(ResourceManager):
13 """
14 Class for managing SCADA data.
15 """
16
17
[docs]
18class 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
[docs]
31class ScadaDataRemoveHandler(ScadaDataBaseHandler):
32 """
33 Class for handling a DELETE request for a given SCADA data instance.
34 """
[docs]
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 <https://falcon.readthedocs.io/en/stable/api/request_and_response_asgi.html#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
[docs]
57class ScadaDataSensorConfigHandler(ScadaDataBaseHandler):
58 """
59 Class for handling GET and POST requests for the sensor configuration
60 of a given SCADA data instance.
61 """
[docs]
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 <https://falcon.readthedocs.io/en/stable/api/request_and_response_asgi.html#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
[docs]
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 <https://falcon.readthedocs.io/en/stable/api/request_and_response_asgi.html#request>`_
91 Request instance.
92 resp : `falcon.Response <https://falcon.readthedocs.io/en/stable/api/request_and_response_asgi.html#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
[docs]
113class ScadaDataSensorFaultsHandler(ScadaDataBaseHandler):
114 """
115 Class for handling GET and POST requests concerning sensor faults in a
116 given SCADA data instance.
117 """
[docs]
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 <https://falcon.readthedocs.io/en/stable/api/request_and_response_asgi.html#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
[docs]
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 <https://falcon.readthedocs.io/en/stable/api/request_and_response_asgi.html#request>`_
147 Request instance.
148 resp : `falcon.Response <https://falcon.readthedocs.io/en/stable/api/request_and_response_asgi.html#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
[docs]
170class ScadaDataConvertUnitsHandler(ScadaDataBaseHandler):
171 """
172 Class for handling POST requests concerning unit conversion of a
173 given SCADA data instance.
174 """
[docs]
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 <https://falcon.readthedocs.io/en/stable/api/request_and_response_asgi.html#request>`_
182 Request instance.
183 resp : `falcon.Response <https://falcon.readthedocs.io/en/stable/api/request_and_response_asgi.html#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