4using System.Collections.Generic;
5using System.ComponentModel;
6using System.Diagnostics.CodeAnalysis;
7using System.Drawing.Design;
10using System.Threading.Tasks;
11using System.Windows.Forms;
15#pragma warning disable 169
36 [SuppressMessage(
"ReSharper",
"MemberCanBePrivate.Global")]
37 [SuppressMessage(
"ReSharper",
"UnusedMember.Global")]
46 INotifyPropertyChanged,
55 #region private variables
59 #endregion private variables
68 internal static readonly List<MockDevice> Instances =
new List<MockDevice>();
72 Instances.Remove(
this);
100 $
"Making a {composition.Volume} mL frappuccino with cream type \"{composition.Cream}\"{(composition.DeCaffeinated ? ", decaffeinated.
" : "")}.");
108 DebugOutput?.Invoke($
"Dummy method of {Name} was called.");
139 #region INeedAConnection
150 #endregion INeedAConnection
152 #region Custom methods and properties
163 $
"The following message was shown addressing the mock device {Name}:\r\n{messageText}",
165 MessageBoxButtons.OK);
166 DebugOutput?.Invoke($
"Finished showing the message {messageText}");
188 #endregion Custom methods and properties
190 #region IProvideStatusMessages
194 #endregion IProvideStatusMessages
196 #region IHaveDebugOutput
200 #endregion IHaveDebugOutput
202 #region INotifyPropertyChanged
210 if (myHandler !=
null)
218 #endregion INotifyPropertyChanged
220 #region IAbortSchedules
241 RestartRemainingJobs =
false
257 throw new OperationCanceledException(
"Aborted");
261 #endregion IAbortSchedules
263 #region Implementation of IHaveMachineParameters<CoffeMakerParams>
270 SetStatusMessage?.Invoke($
"Applying parameters: '{Parameters}' and {(!waitUntilSetpointIsReached ? "not
" : "")} waiting for setpoint.");
271 if (waitUntilSetpointIsReached)
273 return Task.Delay(TimeSpan.FromSeconds(10),canToken);
275 return Task.CompletedTask;
278 #endregion Implementation of IHaveMachineParameters<CoffeMakerParams>
282 WaitHandle.WaitAny(
new[] {
mPauseEnded.WaitHandle, mAborted.WaitHandle });
286 #region Implementation of ICanInterrupt
291 private readonly ManualResetEventSlim
mPauseEnded =
new ManualResetEventSlim(
true);
293 private readonly ManualResetEventSlim
mAborted =
new ManualResetEventSlim(
false);
320 #endregion Implementation of ICanInterrupt
325 public Func<StopRunArgs, Task>
StopRun {
get;
set; }
327 #region Schedule state events
350 DebugOutput?.Invoke($
"Schedule {e.PlanerName} ({e.PlanerID}) state {e.State}, abort reason {(string.IsNullOrEmpty(e.AbortReason) ? "N/A
" : e.AbortReason)}");
356 DebugOutput?.Invoke(
"Starting error handling interaction");
361 DebugOutput?.Invoke(
"Ending error handling interaction");
376 }
while (errArgs.RetryLastAction);
380 throw new IOException($
"Coffee machine reported a problem: {errorDescription}");
383 public event EventHandler<InteractiveErrorHandlingEventArgs>
HandleError;
Classes and interfaces that are meant for plugins. The classes and interfaces below this namespace ar...
ConnectionState
If your connectivity state changes, you should tell the user about it.
ErrorType
Lets a device implementing IHaveInteractiveErrorHandling specify which kind of error occurred.
A fake device. This namespace contains the fake device driver and auxiliary classes for settings,...
Example task implementations. Since there are lots of things that can be done from a task,...
The classes in this namespace demonstrate how to interact with the Chronos sample list.
To be implemented by the "device driver" part of a Chronos plugin.
For devices that need some kind of user configured connection string to address the hardware.
Implement this interface if you want to keep the user up-to-date about what your device is doing.
Implement this interface if you wish to provide debug log output.
Implement this interface if you need to abort schedules on some error condition.
Everything needed for showing the error dialog / reacting on input.
For devices that allow interactive error handling (like retrying the last action)
For devices that support pausing/aborting independent of a task.
Parameters that are constant for the duration of a schedule.
System.Threading.Tasks.TaskFactory GuiTaskFactory
For your convenience, a default task factory for tasks running on the GUI thread.
IWin32Window MainWindow
If you need to set the owner window yourself or want to show message boxes.
Static instance for access to utility functions and resources.
static IGuiHelper Gui
Utility functions for window handling.
Information about the current state change.
Currently starting schedule stage.
Implement this interface if you need to track the state of schedules.
This can be called for a sample list worker or device that writes its own set of log files which shou...
Implement this interface with your device or sample list worker to get fine-grained control about sto...
Options for stopping the schedule/queue.
StopMode
Details how to stop the run.
We have a fancy coffee machine that can regulate the warmer temperature for the pot and has lamps for...
Just a primitive UI Type Editor to demonstrate how you can add an editor of your own for connection s...
A chronos plugin implementation for a fake device. We pretend we are controlling a mixture of coffee ...
PropertyChangedEventHandler PropertyChanged
Action< string > DebugOutput
Action< string > SetStatusMessage
bool Aborted
If set, abort execution as soon as possible. You can throw an OperationCanceledException....
void BrewFrappuccino(BrewFrappuccino.CompositionData composition)
Pretend we are doing some operation on a complex parameter set.
void Connect()
Inform the user of our connect attempt / success. Instead of establishing a real connection,...
readonly ManualResetEventSlim mPauseEnded
Using an event here instead of a simple bool helps us avoid polling while checking for the events.
Action< string > AbortSchedule
void SomeDummyMethod()
Just for testing if methods of this device can be called from some other point in our code.
void OnIsConnectedChanged()
For thread-safe update of the toolbox's GUI elements representing the connection state.
EventHandler< InteractiveErrorHandlingEventArgs > HandleError
void Disconnect()
Pretend we are closing the connection. Actual operation substituted by a message box.
void ScheduleStateChangedHandler(object sender, ScheduleStateEventArgs e)
bool IsConnected
Helper for our toolbox.
Func< StopRunArgs, Task > StopRun
Callback function returning a task that completes once the schedule queue was stopped.
IScheduleEvents mScheduleEvents
void ShowTheMessage(string messageText)
Let our device set a status message and display some message box instead of doing real work.
string Name
User-selected name for the device instance.
Task ApplyParametersAsync(bool waitUntilSetpointIsReached, CancellationToken canToken)
string DisplayedTypeName
Visible to the user on the instruments page of the settings editor.
string DeviceTypeDescription
Device class specification referred to by some messages.
void TriggerAbort(string reason, bool softStop)
This will trigger the AbortSchedule-Event 5 seconds after it was called from a task.
IEnumerable< string > LogPaths
Provide full paths to each of your log files here.
bool Paused
If paused, wait until paused is reset before executing the next command.
void EndInteraction()
Will be called if you can lock the terminal again.
CoffeMakerParams Parameters
string Connection
Connection as set in the Chronos instrument settings.
void BeginInteraction()
Will be called if interaction is started, gives you a chance to unlock a terminal,...
readonly ManualResetEventSlim mAborted
IScheduleEvents ScheduleEvents
Hook up immediately or save this for later use.
Action< ConnectionState > ConnectionStateChanged
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.
const string DeviceTypeName
Provides an endless supply of nonsense sample lists.
static IEnumerable< string > GetFakeLogs(string creator)
Creates a few fake log files.
A task working on a complex parameter set.
Let's pretend the composition is really complex and better done with a custom editor.