Chronos Plugins 5.9.0
This documentation covers the plugin interfaces definitions and an example implementation.
Loading...
Searching...
No Matches
MockPlugin.Device.MockDevice Class Reference

A chronos plugin implementation for a fake device. We pretend we are controlling a mixture of coffee machine and waiter robot. More...

+ Inheritance diagram for MockPlugin.Device.MockDevice:
+ Collaboration diagram for MockPlugin.Device.MockDevice:

Public Member Functions

 MockDevice (IGuiHelper guiHelper)
 
void Dispose ()
 
void BrewFrappuccino (BrewFrappuccino.CompositionData composition)
 Pretend we are doing some operation on a complex parameter set.
 
void SomeDummyMethod ()
 Just for testing if methods of this device can be called from some other point in our code.
 
void Connect ()
 Inform the user of our connect attempt / success. Instead of establishing a real connection, show some message box.
 
void Disconnect ()
 Pretend we are closing the connection. Actual operation substituted by a message box.
 
void ShowTheMessage (string messageText)
 Let our device set a status message and display some message box instead of doing real work.
 
void TriggerAbort (string reason, bool softStop)
 This will trigger the AbortSchedule-Event 5 seconds after it was called from a task.
 
void CheckForAbort ()
 
Task ApplyParametersAsync (bool waitUntilSetpointIsReached, CancellationToken canToken)
 
void WaitIfPaused ()
 
void BeginInteraction ()
 Will be called if interaction is started, gives you a chance to unlock a terminal, for example.
 
void EndInteraction ()
 Will be called if you can lock the terminal again.
 
void RaiseError (string errorDescription, ErrorType errType, bool resolved)
 "Retry" here means that we don't retry some action, but that we raise the error again.
 
- Public Member Functions inherited from AxelSemrau.Chronos.Plugin.IDevice
- Public Member Functions inherited from AxelSemrau.Chronos.Plugin.IHaveMachineParameters< CoffeMakerParams >
Task ApplyParametersAsync (bool waitUntilSetpointIsReached, CancellationToken cancelToken)
 Set the given parameters on the device.
 
- Public Member Functions inherited from AxelSemrau.Chronos.Plugin.IHaveInteractiveErrorHandling

Static Public Attributes

const string DeviceTypeName = "ACME Coffee Maker"
 

Properties

string DisplayedTypeName [get]
 Visible to the user on the instruments page of the settings editor.
 
string DeviceTypeDescription [get]
 Device class specification referred to by some messages.
 
string Name [get, set]
 User-selected name for the device instance.
 
string Connection = "COM17" [get, set]
 Connection as set in the Chronos instrument settings.
 
bool IsConnected [get, set]
 Helper for our toolbox.
 
CoffeMakerParams Parameters = new CoffeMakerParams() [get, set]
 
bool Aborted [get, set]
 If set, abort execution as soon as possible. You can throw an OperationCanceledException. Will be set to false after termination of the run.
 
bool Paused [get, set]
 If paused, wait until paused is reset before executing the next command.
 
IEnumerable< string > LogPaths [get]
 Provide full paths to each of your log files here.
 
Func< StopRunArgs, Task > StopRun [get, set]
 Callback function returning a task that completes once the schedule queue was stopped.
 
IScheduleEvents ScheduleEvents [set]
 Hook up immediately or save this for later use.
 
- Properties inherited from AxelSemrau.Chronos.Plugin.IDevice
- Properties inherited from AxelSemrau.Chronos.Plugin.INeedAConnection
- Properties inherited from AxelSemrau.Chronos.Plugin.ICanInterrupt
- Properties inherited from AxelSemrau.Chronos.Plugin.IHaveMachineParameters< CoffeMakerParams >
ParamType Parameters [get, set]
 Your parameter set.
 
- Properties inherited from AxelSemrau.Chronos.Plugin.IProvideDiagnosticLogs
- Properties inherited from AxelSemrau.Chronos.Plugin.IStopRuns
- Properties inherited from AxelSemrau.Chronos.Plugin.IScheduleStateAware

Events

Action< ConnectionStateConnectionStateChanged
 
Action< string > SetStatusMessage
 
Action< string > DebugOutput
 
PropertyChangedEventHandler PropertyChanged
 
Action< string > AbortSchedule
 
EventHandler< InteractiveErrorHandlingEventArgsHandleError
 
- Events inherited from AxelSemrau.Chronos.Plugin.IDevice
Action< ConnectionStateConnectionStateChanged
 Raise this event when your connection state has changed.
 
- Events inherited from AxelSemrau.Chronos.Plugin.IProvideStatusMessages
Action< string > SetStatusMessage
 Raise this event to set your current status while doing something on the device. Messages passed to this event will be shown in the "Autosampler status" line.
 
- Events inherited from AxelSemrau.Chronos.Plugin.IHaveDebugOutput
Action< string > DebugOutput
 Messages passed to this event will be logged (including a timestamp) to the user configured debug logfile.
 
- Events inherited from AxelSemrau.Chronos.Plugin.IAbortSchedules
Action< string > AbortSchedule
 If you raise this event, the schedule will be aborted.
 
- Events inherited from AxelSemrau.Chronos.Plugin.IHaveInteractiveErrorHandling
EventHandler< InteractiveErrorHandlingEventArgsHandleError
 Raise this event if you want the user to decide how to continue, if this is desired in the settings.
 

Private Member Functions

void OnIsConnectedChanged ()
 For thread-safe update of the toolbox's GUI elements representing the connection state.
 
void ScheduleStateChangedHandler (object sender, ScheduleStateEventArgs e)
 

Private Attributes

bool mIsConnected
 
readonly ManualResetEventSlim mPauseEnded = new ManualResetEventSlim(true)
 Using an event here instead of a simple bool helps us avoid polling while checking for the events.
 
readonly ManualResetEventSlim mAborted = new ManualResetEventSlim(false)
 
IScheduleEvents mScheduleEvents
 
readonly IGuiHelper mGuiHelper
 

Detailed Description

A chronos plugin implementation for a fake device. We pretend we are controlling a mixture of coffee machine and waiter robot.

Just an example implementation that doesn't do any real work.

Definition at line 38 of file MockDevice.cs.

Constructor & Destructor Documentation

◆ MockDevice()

MockPlugin.Device.MockDevice.MockDevice ( IGuiHelper guiHelper)

Definition at line 63 of file MockDevice.cs.

64 {
65 mGuiHelper = guiHelper;
66 Instances.Add(this);
67 }
readonly IGuiHelper mGuiHelper

References MockPlugin.Device.MockDevice.mGuiHelper.

Member Function Documentation

◆ ApplyParametersAsync()

Task MockPlugin.Device.MockDevice.ApplyParametersAsync ( bool waitUntilSetpointIsReached,
CancellationToken canToken )

Definition at line 268 of file MockDevice.cs.

269 {
270
271 SetStatusMessage?.Invoke($"Applying parameters: '{Parameters}' and {(!waitUntilSetpointIsReached ? "not " : "")} waiting for setpoint.");
272 if (waitUntilSetpointIsReached)
273 {
274 return Task.Delay(TimeSpan.FromSeconds(10),canToken);
275 }
276 return Task.CompletedTask;
277 }
Action< string > SetStatusMessage

References MockPlugin.Device.MockDevice.SetStatusMessage.

◆ BeginInteraction()

void MockPlugin.Device.MockDevice.BeginInteraction ( )

Will be called if interaction is started, gives you a chance to unlock a terminal, for example.

Implements AxelSemrau.Chronos.Plugin.IHaveInteractiveErrorHandling.

Definition at line 356 of file MockDevice.cs.

357 {
358 DebugOutput?.Invoke("Starting error handling interaction");
359 }
Action< string > DebugOutput

References MockPlugin.Device.MockDevice.DebugOutput.

◆ BrewFrappuccino()

void MockPlugin.Device.MockDevice.BrewFrappuccino ( BrewFrappuccino.CompositionData composition)

Pretend we are doing some operation on a complex parameter set.

Parameters
composition

Definition at line 97 of file MockDevice.cs.

98 {
101 $"Making a {composition.Volume} mL frappuccino with cream type \"{composition.Cream}\"{(composition.DeCaffeinated ? ", decaffeinated." : "")}.");
102 }
void ShowTheMessage(string messageText)
Let our device set a status message and display some message box instead of doing real work.

References MockPlugin.Device.MockDevice.ShowTheMessage(), and MockPlugin.Device.MockDevice.WaitIfPaused().

Referenced by MockPlugin.Tasks.BrewFrappuccino.Execute().

◆ CheckForAbort()

void MockPlugin.Device.MockDevice.CheckForAbort ( )

Definition at line 254 of file MockDevice.cs.

255 {
256 if (mAborted.IsSet)
257 {
258 throw new OperationCanceledException("Aborted");
259 }
260 }
readonly ManualResetEventSlim mAborted

References MockPlugin.Device.MockDevice.mAborted.

Referenced by MockPlugin.Device.MockDevice.WaitIfPaused().

◆ Connect()

void MockPlugin.Device.MockDevice.Connect ( )

Inform the user of our connect attempt / success. Instead of establishing a real connection, show some message box.

Implements AxelSemrau.Chronos.Plugin.IDevice.

Definition at line 115 of file MockDevice.cs.

116 {
118 MessageBox.Show(mGuiHelper.MainWindow, $"Device {Name} was connected to {Connection}.");
120 mIsConnected = true;
122 }
ConnectionState
If your connectivity state changes, you should tell the user about it.
IWin32Window MainWindow
If you need to set the owner window yourself or want to show message boxes.
Definition Helpers.cs:37
void OnIsConnectedChanged()
For thread-safe update of the toolbox's GUI elements representing the connection state.
Action< ConnectionState > ConnectionStateChanged

References MockPlugin.Device.MockDevice.ConnectionStateChanged, AxelSemrau.Chronos.Plugin.IGuiHelper.MainWindow, MockPlugin.Device.MockDevice.mGuiHelper, MockPlugin.Device.MockDevice.mIsConnected, and MockPlugin.Device.MockDevice.OnIsConnectedChanged().

◆ Disconnect()

void MockPlugin.Device.MockDevice.Disconnect ( )

Pretend we are closing the connection. Actual operation substituted by a message box.

Implements AxelSemrau.Chronos.Plugin.IDevice.

Definition at line 127 of file MockDevice.cs.

128 {
130 MessageBox.Show(mGuiHelper.MainWindow, $"Device {Name} was disconnected from {Connection}.");
132 mIsConnected = false;
134 }

References MockPlugin.Device.MockDevice.ConnectionStateChanged, AxelSemrau.Chronos.Plugin.IGuiHelper.MainWindow, MockPlugin.Device.MockDevice.mGuiHelper, MockPlugin.Device.MockDevice.mIsConnected, and MockPlugin.Device.MockDevice.OnIsConnectedChanged().

◆ Dispose()

void MockPlugin.Device.MockDevice.Dispose ( )

Definition at line 71 of file MockDevice.cs.

72 {
73 Instances.Remove(this);
74 DebugOutput?.Invoke($"MockDevice {Name} disposed");
75 }

References MockPlugin.Device.MockDevice.DebugOutput.

◆ EndInteraction()

void MockPlugin.Device.MockDevice.EndInteraction ( )

Will be called if you can lock the terminal again.

Implements AxelSemrau.Chronos.Plugin.IHaveInteractiveErrorHandling.

Definition at line 361 of file MockDevice.cs.

362 {
363 DebugOutput?.Invoke("Ending error handling interaction");
364 }

References MockPlugin.Device.MockDevice.DebugOutput.

◆ OnIsConnectedChanged()

void MockPlugin.Device.MockDevice.OnIsConnectedChanged ( )
private

For thread-safe update of the toolbox's GUI elements representing the connection state.

Definition at line 208 of file MockDevice.cs.

209 {
210 var myHandler = PropertyChanged;
211 if (myHandler != null)
212 {
213 mGuiHelper.GuiTaskFactory.StartNew(() => myHandler(this, new PropertyChangedEventArgs(nameof(IsConnected))));
214 }
215 }
System.Threading.Tasks.TaskFactory GuiTaskFactory
For your convenience, a default task factory for tasks running on the GUI thread.
Definition Helpers.cs:26
PropertyChangedEventHandler PropertyChanged
bool IsConnected
Helper for our toolbox.

References AxelSemrau.Chronos.Plugin.IGuiHelper.GuiTaskFactory, MockPlugin.Device.MockDevice.IsConnected, MockPlugin.Device.MockDevice.mGuiHelper, and MockPlugin.Device.MockDevice.PropertyChanged.

Referenced by MockPlugin.Device.MockDevice.Connect(), and MockPlugin.Device.MockDevice.Disconnect().

◆ RaiseError()

void MockPlugin.Device.MockDevice.RaiseError ( string errorDescription,
ErrorType errType,
bool resolved )

"Retry" here means that we don't retry some action, but that we raise the error again.

Parameters
errorDescription
errType
resolved

Definition at line 372 of file MockDevice.cs.

373 {
374 var errArgs = new InteractiveErrorHandlingEventArgs() { Error = errorDescription, ErrorType = errType };
375 do
376 {
377 HandleError?.Invoke(this, errArgs);
378 } while (errArgs.RetryLastAction);
379
380 if (!resolved)
381 {
382 throw new IOException($"Coffee machine reported a problem: {errorDescription}");
383 }
384 }
ErrorType
Lets a device implementing IHaveInteractiveErrorHandling specify which kind of error occurred.
Everything needed for showing the error dialog / reacting on input.
EventHandler< InteractiveErrorHandlingEventArgs > HandleError

References MockPlugin.Device.MockDevice.HandleError.

Referenced by MockPlugin.Tasks.CoffeeMachineDoesNotWorkProperly.Execute().

◆ ScheduleStateChangedHandler()

void MockPlugin.Device.MockDevice.ScheduleStateChangedHandler ( object sender,
ScheduleStateEventArgs e )
private

Definition at line 350 of file MockDevice.cs.

351 {
352 DebugOutput?.Invoke($"Schedule {e.PlanerName} ({e.PlanerID}) state {e.State}, abort reason {(string.IsNullOrEmpty(e.AbortReason) ? "N/A" : e.AbortReason)}");
353 }

References MockPlugin.Device.MockDevice.DebugOutput.

◆ ShowTheMessage()

void MockPlugin.Device.MockDevice.ShowTheMessage ( string messageText)

Let our device set a status message and display some message box instead of doing real work.

Parameters
messageText

Definition at line 159 of file MockDevice.cs.

160 {
161 WaitIfPaused();
162 SetStatusMessage?.Invoke("The device just did something wonderful.");
163 MessageBox.Show(mGuiHelper.MainWindow,
164 $"The following message was shown addressing the mock device {Name}:\r\n{messageText}",
165 "Mock Device",
166 MessageBoxButtons.OK);
167 DebugOutput?.Invoke($"Finished showing the message {messageText}");
168 }

References MockPlugin.Device.MockDevice.DebugOutput, AxelSemrau.Chronos.Plugin.IGuiHelper.MainWindow, MockPlugin.Device.MockDevice.mGuiHelper, MockPlugin.Device.MockDevice.SetStatusMessage, and MockPlugin.Device.MockDevice.WaitIfPaused().

Referenced by MockPlugin.Device.MockDevice.BrewFrappuccino(), MockPlugin.Device.MockDeviceToolbox.btnShowMessage_Click(), and MockPlugin.Tasks.BrewCoffee.Execute().

◆ SomeDummyMethod()

void MockPlugin.Device.MockDevice.SomeDummyMethod ( )

Just for testing if methods of this device can be called from some other point in our code.

Definition at line 107 of file MockDevice.cs.

108 {
109 DebugOutput?.Invoke($"Dummy method of {Name} was called.");
110 }

References MockPlugin.Device.MockDevice.DebugOutput.

◆ TriggerAbort()

void MockPlugin.Device.MockDevice.TriggerAbort ( string reason,
bool softStop )

This will trigger the AbortSchedule-Event 5 seconds after it was called from a task.

Parameters
reason
softStop

For a real device, this would be something like a leak, a failed pump or heater or anything else that makes it impossible to operate the device properly.

Definition at line 232 of file MockDevice.cs.

233 {
234 Task.Run(() =>
235 {
236 Thread.Sleep(5000);
237 if (softStop)
238 {
239 StopRun?.Invoke(new StopRunArgs()
240 {
241 How = StopRunArgs.StopMode.NoNewJobs, StopQueue = true, Reason = reason,
242 RestartRemainingJobs = false
243 });
244 }
245 else
246 {
247 AbortSchedule?.Invoke(reason);
248 }
249 });
250}
Options for stopping the schedule/queue.
StopMode
Details how to stop the run.
Action< string > AbortSchedule
Func< StopRunArgs, Task > StopRun
Callback function returning a task that completes once the schedule queue was stopped.

References MockPlugin.Device.MockDevice.AbortSchedule, and MockPlugin.Device.MockDevice.StopRun.

Referenced by MockPlugin.Tasks.PretendCoffeeMachineIsBroken.Execute().

◆ WaitIfPaused()

void MockPlugin.Device.MockDevice.WaitIfPaused ( )

Definition at line 281 of file MockDevice.cs.

282 {
283 WaitHandle.WaitAny(new[] { mPauseEnded.WaitHandle, mAborted.WaitHandle });
285 }
readonly ManualResetEventSlim mPauseEnded
Using an event here instead of a simple bool helps us avoid polling while checking for the events.

References MockPlugin.Device.MockDevice.CheckForAbort(), and MockPlugin.Device.MockDevice.mPauseEnded.

Referenced by MockPlugin.Device.MockDevice.BrewFrappuccino(), and MockPlugin.Device.MockDevice.ShowTheMessage().

Member Data Documentation

◆ DeviceTypeName

const string MockPlugin.Device.MockDevice.DeviceTypeName = "ACME Coffee Maker"
static

Definition at line 54 of file MockDevice.cs.

◆ mAborted

readonly ManualResetEventSlim MockPlugin.Device.MockDevice.mAborted = new ManualResetEventSlim(false)
private

Definition at line 294 of file MockDevice.cs.

Referenced by MockPlugin.Device.MockDevice.CheckForAbort().

◆ mGuiHelper

◆ mIsConnected

bool MockPlugin.Device.MockDevice.mIsConnected
private

◆ mPauseEnded

readonly ManualResetEventSlim MockPlugin.Device.MockDevice.mPauseEnded = new ManualResetEventSlim(true)
private

Using an event here instead of a simple bool helps us avoid polling while checking for the events.

Definition at line 292 of file MockDevice.cs.

Referenced by MockPlugin.Device.MockDevice.WaitIfPaused().

◆ mScheduleEvents

IScheduleEvents MockPlugin.Device.MockDevice.mScheduleEvents
private

Definition at line 330 of file MockDevice.cs.

Property Documentation

◆ Aborted

bool MockPlugin.Device.MockDevice.Aborted
getset

If set, abort execution as soon as possible. You can throw an OperationCanceledException. Will be set to false after termination of the run.

Implements AxelSemrau.Chronos.Plugin.ICanInterrupt.

Definition at line 296 of file MockDevice.cs.

297 {
298 get => mAborted.IsSet;
299 set
300 {
301 if (value) { mAborted.Set(); } else { mAborted.Reset(); }
302 }
303 }

◆ Connection

string MockPlugin.Device.MockDevice.Connection = "COM17"
getset

Connection as set in the Chronos instrument settings.

If this gets a bit more complicated, you can also use a UITypeEditor here.

Implements AxelSemrau.Chronos.Plugin.INeedAConnection.

Definition at line 149 of file MockDevice.cs.

149{ get; set; } = "COM17";

◆ DeviceTypeDescription

string MockPlugin.Device.MockDevice.DeviceTypeDescription
get

Device class specification referred to by some messages.

Implements AxelSemrau.Chronos.Plugin.IDevice.

Definition at line 85 of file MockDevice.cs.

◆ DisplayedTypeName

string MockPlugin.Device.MockDevice.DisplayedTypeName
get

Visible to the user on the instruments page of the settings editor.

Implements AxelSemrau.Chronos.Plugin.IDevice.

Definition at line 80 of file MockDevice.cs.

◆ IsConnected

bool MockPlugin.Device.MockDevice.IsConnected
getset

Helper for our toolbox.

Definition at line 173 of file MockDevice.cs.

174 {
175 get => mIsConnected;
176 set
177 {
178 if (!mIsConnected && value)
179 {
180 Connect();
181 }
182 else if (mIsConnected && !value)
183 {
184 Disconnect();
185 }
186 }
187 }
void Connect()
Inform the user of our connect attempt / success. Instead of establishing a real connection,...
void Disconnect()
Pretend we are closing the connection. Actual operation substituted by a message box.

Referenced by MockPlugin.Device.MockDevice.OnIsConnectedChanged().

◆ LogPaths

IEnumerable<string> MockPlugin.Device.MockDevice.LogPaths
get

Provide full paths to each of your log files here.

Implements AxelSemrau.Chronos.Plugin.IProvideDiagnosticLogs.

Definition at line 323 of file MockDevice.cs.

◆ Name

string MockPlugin.Device.MockDevice.Name
getset

User-selected name for the device instance.

Please return what you are given. Note: Before Chronos 5.1.8, this was set to "Uninitialized Device" for temporary device instances. With later versions, the name should only be set for a "real" instance.

Implements AxelSemrau.Chronos.Plugin.IDevice.

Definition at line 87 of file MockDevice.cs.

88 {
89 get;
90 set;
91 }

Referenced by MockPlugin.Tasks.BrewCoffee.RegisterCoffeeConsumption(), MockPlugin.Tasks.BrewFrappuccino.RegisterConsumption(), and MockPlugin.Misc.StatusViewControl.timer1_Tick().

◆ Parameters

CoffeMakerParams MockPlugin.Device.MockDevice.Parameters = new CoffeMakerParams()
getset

Definition at line 266 of file MockDevice.cs.

266{ get; set; } = new CoffeMakerParams();

◆ Paused

bool MockPlugin.Device.MockDevice.Paused
getset

If paused, wait until paused is reset before executing the next command.

Implements AxelSemrau.Chronos.Plugin.ICanInterrupt.

Definition at line 305 of file MockDevice.cs.

306 {
307 get => !mPauseEnded.IsSet;
308 set
309 {
310 if (value)
311 {
312 mPauseEnded.Reset();
313 }
314 else
315 {
316 mPauseEnded.Set();
317 }
318 }
319 }

◆ ScheduleEvents

IScheduleEvents MockPlugin.Device.MockDevice.ScheduleEvents
set

Hook up immediately or save this for later use.

Implements AxelSemrau.Chronos.Plugin.IScheduleStateAware.

Definition at line 333 of file MockDevice.cs.

334 {
335 set
336 {
337 if (mScheduleEvents != null)
338 {
339 mScheduleEvents.ScheduleStateChanged -= ScheduleStateChangedHandler;
340 }
341
342 mScheduleEvents = value;
343 if (value != null)
344 {
345 mScheduleEvents.ScheduleStateChanged += ScheduleStateChangedHandler;
346 }
347 }
348 }
void ScheduleStateChangedHandler(object sender, ScheduleStateEventArgs e)
IScheduleEvents mScheduleEvents

◆ StopRun

Func<StopRunArgs, Task> MockPlugin.Device.MockDevice.StopRun
getset

Callback function returning a task that completes once the schedule queue was stopped.

Implements AxelSemrau.Chronos.Plugin.IStopRuns.

Definition at line 326 of file MockDevice.cs.

326{ get; set; }

Referenced by MockPlugin.Device.MockDevice.TriggerAbort().

Event Documentation

◆ AbortSchedule

Action<string> MockPlugin.Device.MockDevice.AbortSchedule

Definition at line 252 of file MockDevice.cs.

Referenced by MockPlugin.Device.MockDevice.TriggerAbort().

◆ ConnectionStateChanged

Action<ConnectionState> MockPlugin.Device.MockDevice.ConnectionStateChanged

◆ DebugOutput

◆ HandleError

EventHandler<InteractiveErrorHandlingEventArgs> MockPlugin.Device.MockDevice.HandleError

Definition at line 385 of file MockDevice.cs.

Referenced by MockPlugin.Device.MockDevice.RaiseError().

◆ PropertyChanged

PropertyChangedEventHandler MockPlugin.Device.MockDevice.PropertyChanged

Definition at line 217 of file MockDevice.cs.

Referenced by MockPlugin.Device.MockDevice.OnIsConnectedChanged().

◆ SetStatusMessage

Action<string> MockPlugin.Device.MockDevice.SetStatusMessage

The documentation for this class was generated from the following file: