Using and extending EUT monitoring¶
EUT monitoring is part of every immunity test. mpylab separates three responsibilities:
monitors observe the EUT and produce structured events;
the measurement kernel decides whether to continue, retry, or stop;
the measurement worker immediately performs safety actions such as RF-off.
A monitor therefore does not access MGraph or RF instruments directly.
Manual intervention remains available alongside automatic monitoring. The
complete event structure and assessment rules are documented separately.
Using existing measurement classes¶
MSC.Measure_Immunity and TEMCell.Measure_Immunity accept the same
fundamental parameters:
eut_monitorOne automatic
EUTMonitoror a sequence of monitors.manual_eut_monitorOptional manual monitor owned by a UI. When omitted, the measurement class creates a keyboard-backed fallback.
performance_criterionPerformance criterion
"A","B", or"C":A: The EUT must operate as intended during and after exposure without unacceptable degradation.
B: Temporary degradation during exposure is permitted. Afterwards, the EUT must recover normal operation automatically; its operating mode and stored data must not be lost.
C: Temporary loss of function is permitted. Normal operation may be restored automatically, by operator intervention, or by reset.
The applicable product standard may refine these general criteria or add further requirements.
post_exposure_timeoutObservation time after RF-off. This is particularly relevant when assessing recovery under criterion B or C.
eut_event_policyApplication decision for
degraded,failed, andnot_evaluated. Thesafety_action="rf_off"request is handled independently of this policy.
Use a reproducible virtual monitor for the first run:
from mpylab.env.eut import VirtualEUTMonitor
monitor = VirtualEUTMonitor([{
"status": "degraded",
"reason": "virtual_output_tolerance",
"safety_action": "none",
}])
status = measurement.Measure_Immunity(
description="EUT",
eut_monitor=monitor,
performance_criterion="B",
post_exposure_timeout=10.0,
eut_event_policy={
"degraded": "continue",
"failed": "stop",
"not_evaluated": "stop",
"max_retries": 0,
},
# further method-specific parameters
)
The MSC threshold search receives its monitor in the
ImmunityThresholdKernel parameter block. Qt applications pass their
ManualEUTMonitor and automatic monitors to the measurement class.
TEMField provides set_automatic_eut_monitor for this purpose. See the
MSC and TEM guides for their complete workflows.
Developing a specific monitor¶
An application-specific monitor derives from EUTMonitor. Typical sources
include camera images, communication responses, digital states, or process
measurements. poll_event must be non-blocking or have a clearly bounded
runtime:
from mpylab.env.eut import EUTMonitor, make_eut_event
class CommunicationEUTMonitor(EUTMonitor):
def start_exposure(self, context):
self.frequency = context.get("frequency")
self.start_observation()
def poll_event(self):
observation = self.read_status_nonblocking()
if observation is None:
return None
if observation == "ok":
return make_eut_event(
"passed",
"communication_ok",
source="eut_link",
)
return make_eut_event(
"failed",
"communication_lost",
details={"frequency": self.frequency},
safety_action="rf_off",
source="eut_link",
)
def stop_exposure(self):
self.stop_observation()
def close(self):
self.close_connection()
Wrap instrument access with significant latency:
from mpylab.env.eut import ThreadedEUTMonitor
monitor = ThreadedEUTMonitor(
CommunicationEUTMonitor(),
poll_interval=0.02,
join_timeout=1.0,
)
The wrapped poll_event call must still have a finite maximum runtime so
that the thread can terminate safely. Failure of an automatic monitor is
stored as monitor_diagnostic and must not be reported as an observed EUT
failure.
Integrating a new application¶
EUTMonitoringSession combines manual and automatic monitors and manages
exposure lifecycle, phases, event validation, and diagnostics:
from mpylab.env.eut import EUTMonitoringSession, ManualEUTMonitor
manual = ManualEUTMonitor(poll_key=my_poll_key, keylist="sS")
session = EUTMonitoringSession.from_monitors(manual, [monitor])
try:
session.start_exposure({"frequency": frequency, "position": position})
event = session.poll_event()
if event is not None and event["safety_action"] == "rf_off":
measurement_worker.rf_off() # immediate safety path
session.start_phase(
"post_exposure",
{"frequency": frequency, "position": position, "rf_on": False},
)
finally:
session.close()
The session never switches RF itself. A new measurement application must
perform safety actions in its worker, preserve monitor events in the
measurement history, and call close from a finally block. RF-off must
precede monitor cleanup that might fail.
Testing without hardware¶
VirtualEUTMonitoremits predefined events deterministically.RandomEUTMonitor(seed=...)is useful for longer workflow and UI tests, but does not demonstrate real EUT behavior.Tests must cover manual intervention, immediate RF-off, post-exposure, monitor diagnostics, and cleanup failures.
A virtual end-to-end run should use the same measurement-class parameters as the later hardware run.
The curated Python API documents every public monitor and session method. Thread and GUI rules are covered by UI adapters and worker interface.