4 @copyright 2022 ESO - European Southern Observatory
6 @brief Implements simulation of recdaqif
16 from astropy.io
import fits
17 from ModDaqsimif.Daqsimif
import Error
as SimCtlError
18 from ModRecif.Recif
import (ExceptionErr, RecProperties, RecStatus,
19 RecStatusNames, RecWaitSpec, RecWaitStatus,
21 from ModRecif.Recif.RecCmds
import RecCmdsSyncService
25 """Holds simulated status for recording"""
39 self.
statusstatus = RecStatusNames.Undefined
43 """Simulator that implements RecCmdsSyncService and sets up
44 simulation behaviour for Simulator.
46 Registered hooks are run once and then removed before executed.
47 Each hook is a callable that takes the result from the default implementation
48 as well as the arguments given to the original implementation.
49 The hook can then choose to modify the existing result or replace it.
61 def RecStart(self, properties: RecProperties) -> RecStatus:
62 """@implements RecCmds.StartDaq"""
63 rec_id = properties.getId()
64 logging.info(
"Request: StartDaq(%s)", rec_id)
66 raise ExceptionErr(
"Recording with id already exist: %s" % rec_id, 1234)
68 logging.info(
"Request: RecStart(%s) ref=%s", rec_id, id(rec))
69 rec.status = RecStatusNames.Active
75 """@implements RecCmds.RecStop"""
78 raise ExceptionErr(
"No current recording active", 1234)
80 logging.info(
"Request: RecStop(%s)", rec_id)
84 if rec.status
in (RecStatusNames.Completed, RecStatusNames.Stopped):
86 "Request: RecStop(%s): Recording already complete. Returning error",
89 raise ExceptionErr(
"Recording already stopped '%s'" % rec_id, 1234)
91 path = os.path.join(self.
datarootdataroot,
"%s_%s.fits" % (rec_id, self.
namename))
92 start = time.monotonic()
93 hdul = fits.HDUList([fits.PrimaryHDU()])
94 hdul.append(fits.ImageHDU(np.ones((100, 100)), name=self.
namename))
96 stop = time.monotonic()
98 "Request: RecStop(%s): FITS written to %s (took %.1fs)",
104 rec.dp_files = [path]
105 rec.status = RecStatusNames.Stopped
111 except Exception
as e:
112 logging.exception(
"RecStop failed")
113 raise ExceptionErr(
"RecStop failed: {str(e)}", 1234)
116 """@implements RecCmds.RecAbort"""
118 raise ExceptionErr(
"No current recording active", 1234)
122 logging.info(
"Request: RecAbort(%s)", rec_id)
124 rec.status = RecStatusNames.Aborted
129 except Exception
as e:
130 logging.exception(
"RecAbort faied")
131 raise ExceptionErr(
"RecAbort failed: {str(e)}", 1234)
133 logging.exception(
"RecAbort faied with unknown error")
134 raise ExceptionErr(
"RecAbort failed with unknown error", 1234)
137 self, spec: RecWaitSpec
139 """@implements RecCmds.RecWait
141 For the moment we simply simulate that the recording was completed
142 as soon as this request was received.
145 logging.info(
"Request: RecWait(%s)", rec_id)
149 def RecStatus(self, rec_id: str) -> RecStatus:
150 """@implements RecCmds.RecStatus"""
151 logging.info(
"Request: RecStatus(%s)", rec_id)
156 """@implements RecCmds.RecPause"""
157 logging.info(
"Request: RecPause(): Throwing not implemented error")
158 raise ExceptionErr(
"Not implemented", 1234)
161 """Get recording or raise ExceptionErr."""
164 raise ExceptionErr(
"Unknown recording id '%s'" % rec_id, 1234)
168 <struct name="RecStatus">
169 <member name="dpFiles" type="string" arrayDimensions="(32)"/>
170 <member name="endTime" type="double"/>
171 <member name="filesGenerated" type="int32_t"/>
172 <member name="framesProcessed" type="int32_t"/>
173 <member name="framesRemaining" type="int32_t"/>
174 <member name="id" type="string"/>
175 <member name="info" type="string"/>
176 <member name="remainingTime" type="double"/>
177 <member name="sizeRecorded" type="int32_t"/>
178 <member name="startTime" type="double"/>
179 <member name="status" type="nonBasic" nonBasicTypeName="RecStatusNames"/>
180 <member name="timeElapsed" type="double"/>
183 logging.debug(
"Creating return type: RecStatus for id %s", rec_id)
185 status = self.
malmal.createDataEntity(RecStatus)
190 """Populates RecStatus from status"""
192 "Populating return type: RecStatus: id=%s, status=%r (ref=%s)",
197 status.setDpFiles(rec.dp_files)
198 status.setEndTime(rec.end_time)
199 status.setFilesGenerated(rec.files_generated)
200 status.setFramesProcessed(rec.frames_processed)
201 status.setFramesRemaining(rec.frames_remaining)
203 status.setInfo(rec.info)
204 status.setRemainingTime(rec.remaining_time)
205 status.setSizeRecorded(rec.size_recorded)
206 status.setStartTime(rec.start_time)
207 status.setStatus(rec.status)
208 status.setTimeElapsed(rec.time_elapsed)
211 """Creates RecWaitStatus and populates attributes"""
212 logging.debug(
"Creating return type: RecWaitStatus")
214 status = self.
malmal.createDataEntity(RecWaitStatus)
216 if rec.status
in (RecStatusNames.Completed, RecStatusNames.Stopped):
218 "Recording is Completed or Stopped, RecWaitStatus set to success"
220 status.setStatus(RecWaitStatusNames.Success)
222 status.setStatus(RecWaitStatusNames.Timeout)
226 """Add the simulation hook `hook` for the specified command `cmd_name` (e.g.
229 Any previous hooks will be replaced.
234 """Reset simulator to initial default state."""
240 """Remove all simulation hooks."""
244 """Runs simulation hook that may modify or replace the default implementation.
246 The hook to execute is automatically determined from the call stack, so
247 this should only ever be executed directly from the service command
248 implementation method.
250 cmd_name = inspect.stack()[1][3]
251 hook = self.
sim_hookssim_hooks.get(cmd_name)
252 logging.debug(
"Checking for hook for command %s", cmd_name)
254 logging.debug(
"Running simulation hook for command %s", cmd_name)
256 return hook(result, *args)
259 "No hook for %s, returning %s (%s)", cmd_name, result, type(result)
265 """Simulator controller that implements ModDaqsimif and sets up
266 simulation behaviour for Simulator.
276 logging.info(
"Registering service 'rec'")
277 self.
serverserver.registerService(
"rec", RecCmdsSyncService, self.
simsim)
279 def Setup(self, spec):
280 """@implements SimCtl.Setup."""
281 logging.info(
'SimCtl.Setup: spec="%s"', spec)
284 cmd = s.get(
"command",
"")
285 action = s.get(
"action",
"")
286 if action ==
"complete-recording":
288 rec = self.
simsim.current_rec
290 "SimCtl.Setup: Marking %s as Completed ref=%s", rec.id, id(rec)
292 rec.status = RecStatusNames.Completed
294 self.
datarootdataroot,
"auto_%s_%s.fits" % (rec.id, self.
namename)
297 hdul = fits.HDUList([fits.PrimaryHDU()])
298 hdul.append(fits.ImageHDU(np.ones((100, 100)), name=self.
namename))
300 logging.info(
"SimCtl.Setup: %s FITS written to %s", rec.id, path)
301 rec.dp_files = [path]
302 assert id(self.
simsim.get_recording(rec.id)) == id(rec)
304 elif action ==
"throw":
306 def throw(res, *args):
307 logging.debug(
"Throwing exception")
309 "Simulated error (current id: %s)"
310 % getattr(self.
simsim.current_rec,
"id",
"n/a"),
314 self.
simsim.add_sim_hook(cmd, throw)
316 raise SimCtlError(
"Unknown action '%s' provided" % action)
317 logging.info(
"SimCtl.Setup: Returning empty string")
318 return json.dumps(
"")
320 logging.exception(
"SimCtl.Setup: Failed")
322 except Exception
as e:
323 logging.exception(
"SimCtl.Setup: Failed")
324 raise SimCtlError(
'"%s"' % str(e))
327 """@implements SimCtl.Reset"""
330 except Exception
as e:
331 raise SimCtlError(str(e))
334 """@implements SimCtl.ForceExit."""
336 logging.warning(
"Force Exiting without cleanup!")
Holds simulated status for recording.
Simulator controller that implements ModDaqsimif and sets up simulation behaviour for Simulator.
def __init__(self, name, mal, server, dataroot)
Simulator that implements RecCmdsSyncService and sets up simulation behaviour for Simulator.
Recording get_recording(self, rec_id)
Get recording or raise ExceptionErr.
RecStatus RecStatus(self, str rec_id)
RecStatus populate_rec_status(self, Recording rec, RecStatus status)
Populates RecStatus from status.
def add_sim_hook(self, str cmd_name, hook)
Add the simulation hook hook for the specified command cmd_name (e.g.
RecStatus RecStart(self, RecProperties properties)
RecStatus make_rec_status(self, rec_id)
<struct name="RecStatus"> <member name="dpFiles" type="string" arrayDimensions="(32)"> <member name="...
RecStatus RecWait(self, RecWaitSpec spec)
RecWaitStatus make_rec_wait_status(self, rec_id)
Creates RecWaitStatus and populates attributes.
def reset(self)
Reset simulator to initial default state.
def run_sim_hook(self, result, *args)
Runs simulation hook that may modify or replace the default implementation.
def clear_sim_hooks(self)
Remove all simulation hooks.
def __init__(self, name, mal, dataroot)