Skip to content

Commit

Permalink
Version 3.3-rc3
Browse files Browse the repository at this point in the history
Updated WHATS_NEW
Bug fix: Simulation times were not correctly written to job files
Bug fix: When simulation time was present, they were always interpreted as print time
  • Loading branch information
chrishamm committed May 24, 2021
1 parent d5fd48a commit a5d8b28
Show file tree
Hide file tree
Showing 6 changed files with 76 additions and 40 deletions.
2 changes: 2 additions & 0 deletions WHATS_NEW.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ Bug fixes:
- When DCS was configured to never terminate on reset, sometimes it failed to establish a connection again
- Subscribe connection clients failed to clear `global` dictionary on reset
- Fixed `exists` function in conditional G-code
- When retrieving file info, DCS returned the simulated time instead of the slicer time
- Fixed timing issue causing simulation times to be written incorrectly to G-code files

Known limitations:
- Auto-resume on power loss cannot be configured (M916)
Expand Down
1 change: 0 additions & 1 deletion src/DuetAPI/ObjectModel/Plugins/PluginManifest.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
using DuetAPI.Utility;
using System;
using System.Text.Json;

namespace DuetAPI.ObjectModel
{
Expand Down
11 changes: 5 additions & 6 deletions src/DuetControlServer/FileExecution/Job.cs
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,7 @@ public static async Task Run()
_logger.Info("Starting file print");

// Notify RRF
SPI.Interface.SetPrintStarted();
SPI.Interface.StartPrint();

// Process the file
Queue<Code> codes = new();
Expand Down Expand Up @@ -369,27 +369,26 @@ public static async Task Run()
// Notify RepRapFirmware that the print file has been closed
if (IsCancelled)
{
await SPI.Interface.StopPrint(PrintStoppedReason.UserCancelled);
_logger.Info("Cancelled job file");
await SPI.Interface.SetPrintStopped(PrintStoppedReason.UserCancelled);
}
else if (IsAborted)
{
await SPI.Interface.StopPrint(PrintStoppedReason.Abort);
_logger.Info("Aborted job file");
await SPI.Interface.SetPrintStopped(PrintStoppedReason.Abort);
}
else
{
await SPI.Interface.StopPrint(PrintStoppedReason.NormalCompletion);
_logger.Info("Finished job file");
await SPI.Interface.SetPrintStopped(PrintStoppedReason.NormalCompletion);
}

// Update the object model again
// Update special fields that are not available in RRF
using (await Provider.AccessReadWriteAsync())
{
Provider.Get.Job.LastFileAborted = IsAborted;
Provider.Get.Job.LastFileCancelled = IsCancelled;
Provider.Get.Job.LastFileSimulated = IsSimulating;
Provider.Get.Job.LastFileName = Provider.Get.Job.File.FileName;
}

// Update the last simulated time
Expand Down
8 changes: 4 additions & 4 deletions src/DuetControlServer/Files/InfoParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -114,11 +114,11 @@ private static async Task ParseHeader(StreamReader reader, ParsedFileInfo partia
}
else if (!string.IsNullOrWhiteSpace(code.Comment))
{
gotNewInfo |= (partialFileInfo.SimulatedTime == null) && FindSimulatedTime(code.Comment, ref partialFileInfo);
gotNewInfo |= !gotNewInfo && (partialFileInfo.PrintTime == null) && FindPrintTime(code.Comment, ref partialFileInfo);
gotNewInfo |= (partialFileInfo.LayerHeight == 0) && FindLayerHeight(code.Comment, ref partialFileInfo);
gotNewInfo |= FindFilamentUsed(code.Comment, ref partialFileInfo);
gotNewInfo |= string.IsNullOrEmpty(partialFileInfo.GeneratedBy) && FindGeneratedBy(code.Comment, ref partialFileInfo);
gotNewInfo |= (partialFileInfo.PrintTime == null) && FindPrintTime(code.Comment, ref partialFileInfo);
gotNewInfo |= (partialFileInfo.SimulatedTime == null) && FindSimulatedTime(code.Comment, ref partialFileInfo);
}

// Is the file info complete?
Expand Down Expand Up @@ -190,11 +190,11 @@ private static async Task ParseFooter(StreamReader reader, ParsedFileInfo partia
}
else if (!string.IsNullOrWhiteSpace(code.Comment))
{
gotNewInfo |= (partialFileInfo.SimulatedTime == null) && FindSimulatedTime(code.Comment, ref partialFileInfo);
gotNewInfo |= !gotNewInfo && (partialFileInfo.PrintTime == null) && FindPrintTime(code.Comment, ref partialFileInfo);
gotNewInfo |= (partialFileInfo.LayerHeight == 0) && FindLayerHeight(code.Comment, ref partialFileInfo);
gotNewInfo |= !hadFilament && FindFilamentUsed(code.Comment, ref partialFileInfo);
gotNewInfo |= string.IsNullOrEmpty(partialFileInfo.GeneratedBy) && FindGeneratedBy(code.Comment, ref partialFileInfo);
gotNewInfo |= (partialFileInfo.PrintTime == null) && FindPrintTime(code.Comment, ref partialFileInfo);
gotNewInfo |= (partialFileInfo.SimulatedTime == null) && FindSimulatedTime(code.Comment, ref partialFileInfo);
}

// Prepare to read the next code
Expand Down
39 changes: 27 additions & 12 deletions src/DuetControlServer/Model/Updater.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,22 @@ public static class Updater
/// <summary>
/// General-purpose lock for this class
/// </summary>
private static readonly AsyncMonitor _monitor = new();
private static readonly AsyncLock _lock = new();

/// <summary>
/// First condition variable for object model updates
/// </summary>
private static readonly AsyncConditionVariable _updateConditionA = new(_lock);

/// <summary>
/// First condition variable for object model updates
/// </summary>
private static readonly AsyncConditionVariable _updateConditionB = new(_lock);

/// <summary>
/// Whether a client waiting for an object model update shall use A or B
/// </summary>
private static bool _useUpdateConditionA;

/// <summary>
/// Dictionary of main keys vs last sequence numbers
Expand All @@ -38,9 +53,9 @@ public static class Updater
/// <returns>Asynchronous task</returns>
public static async Task WaitForFullUpdate(CancellationToken cancellationToken)
{
using (await _monitor.EnterAsync(cancellationToken))
using (await _lock.LockAsync(cancellationToken))
{
await _monitor.WaitAsync(cancellationToken);
await (_useUpdateConditionA ? _updateConditionA : _updateConditionB).WaitAsync(cancellationToken);
Program.CancellationToken.ThrowIfCancellationRequested();
}
}
Expand All @@ -51,9 +66,10 @@ public static async Task WaitForFullUpdate(CancellationToken cancellationToken)
/// <returns>Asynchronous task</returns>
public static async Task MachineModelFullyUpdated()
{
using (await _monitor.EnterAsync(Program.CancellationToken))
using (await _lock.LockAsync(Program.CancellationToken))
{
_monitor.PulseAll();
_useUpdateConditionA = !_useUpdateConditionA;
(_useUpdateConditionA ? _updateConditionA : _updateConditionB).NotifyAll();
}
}

Expand All @@ -65,7 +81,7 @@ public static async Task MachineModelFullyUpdated()
public static async Task ProcessLegacyConfigResponse(byte[] response)
{
using JsonDocument jsonDocument = JsonDocument.Parse(response);
using (await _monitor.EnterAsync(Program.CancellationToken))
using (await _lock.LockAsync(Program.CancellationToken))
{
if (jsonDocument.RootElement.TryGetProperty("boardName", out JsonElement boardName))
{
Expand Down Expand Up @@ -94,7 +110,8 @@ public static async Task ProcessLegacyConfigResponse(byte[] response)
}

// Cannot perform any further updates...
_monitor.PulseAll();
_useUpdateConditionA = !_useUpdateConditionA;
(_useUpdateConditionA ? _updateConditionA : _updateConditionB).NotifyAll();

// Check if the firmware is supposed to be updated
if (Settings.UpdateOnly && !_updatingFirmware)
Expand Down Expand Up @@ -123,7 +140,7 @@ public static async Task Run()
try
{
// Request the limits if no sequence numbers have been set yet
using (await _monitor.EnterAsync(Program.CancellationToken))
using (await _lock.LockAsync(Program.CancellationToken))
{
if (_lastSeqs.IsEmpty)
{
Expand Down Expand Up @@ -223,10 +240,8 @@ public static async Task Run()
}

// Object model is now up-to-date, notify waiting clients
using (await _monitor.EnterAsync(Program.CancellationToken))
{
_monitor.PulseAll();
}
_useUpdateConditionA = !_useUpdateConditionA;
(_useUpdateConditionA ? _updateConditionA : _updateConditionB).NotifyAll();

// Check if the firmware is supposed to be updated
if (Settings.UpdateOnly && !_updatingFirmware)
Expand Down
55 changes: 38 additions & 17 deletions src/DuetControlServer/SPI/Interface.cs
Original file line number Diff line number Diff line change
Expand Up @@ -80,11 +80,15 @@ private sealed class PendingModelQuery
private static TaskCompletionSource _firmwareHaltRequest;
private static TaskCompletionSource _firmwareResetRequest;

// Print handling
private static volatile bool _startPrint;
private static readonly AsyncLock _stopPrintLock = new();
private static PrintStoppedReason _stopPrintReason;
private static TaskCompletionSource _stopPrintRequest;

// Miscellaneous requests
private static volatile bool _assignFilaments;
private static readonly Dictionary<int, string> _extruderFilamentMapping = new();
private static readonly AsyncLock _printStopppedReasonLock = new();
private static PrintStoppedReason? _printStoppedReason;
private static volatile bool _printStarted, _assignFilaments;
private static readonly Queue<Tuple<MessageTypeFlags, string>> _messagesToSend = new();

// Partial incoming message (if any)
Expand Down Expand Up @@ -418,33 +422,40 @@ public static async Task ResetFirmware()
/// Notify the firmware that a file print has started
/// </summary>
/// <exception cref="InvalidOperationException">Not connected over SPI</exception>
public static void SetPrintStarted()
public static void StartPrint()
{
if (Settings.NoSpi)
{
throw new InvalidOperationException("Not connected over SPI");
}

_printStarted = true;
_startPrint = true;
}

/// <summary>
/// Notify the firmware that the file print has been stopped
/// </summary>
/// <param name="stopReason">Reason why the print has stopped</param>
/// <param name="reason">Reason why the print has stopped</param>
/// <returns>Asynchronous task</returns>
/// <exception cref="InvalidOperationException">Not connected over SPI</exception>
public static async Task SetPrintStopped(PrintStoppedReason stopReason)
public static async Task StopPrint(PrintStoppedReason reason)
{
if (Settings.NoSpi)
{
throw new InvalidOperationException("Not connected over SPI");
}

using (await _printStopppedReasonLock.LockAsync(Program.CancellationToken))
Task onPrintStopped;
using (await _stopPrintLock.LockAsync(Program.CancellationToken))
{
_printStoppedReason = stopReason;
_stopPrintReason = reason;
if (_stopPrintRequest == null)
{
_stopPrintRequest = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously);
}
onPrintStopped = _stopPrintRequest.Task;
}
await onPrintStopped;
}

/// <summary>
Expand Down Expand Up @@ -804,20 +815,21 @@ public static async Task Run()

// Check for changes of the print status.
// The packet providing file info has be sent first because it includes a time_t value that must reside on a 64-bit boundary!
if (_printStarted)
if (_startPrint)
{
using (await Model.Provider.AccessReadOnlyAsync())
{
_printStarted = !DataTransfer.WritePrintStarted(Model.Provider.Get.Job.File);
_startPrint = !DataTransfer.WritePrintStarted(Model.Provider.Get.Job.File);
}
}
else
{
using (await _printStopppedReasonLock.LockAsync(Program.CancellationToken))
using (await _stopPrintLock.LockAsync(Program.CancellationToken))
{
if (_printStoppedReason != null && DataTransfer.WritePrintStopped(_printStoppedReason.Value))
if (_stopPrintRequest != null && DataTransfer.WritePrintStopped(_stopPrintReason))
{
_printStoppedReason = null;
_stopPrintRequest.SetResult();
_stopPrintRequest = null;
}
}
}
Expand Down Expand Up @@ -1532,18 +1544,27 @@ private static async Task Invalidate(string message)
}
}

// Clear messages to send to the firmware
lock (_messagesToSend)
// No longer stopping a print
_startPrint = false;
if (_stopPrintRequest != null)
{
_messagesToSend.Clear();
_stopPrintRequest.SetResult();
_stopPrintRequest = null;
}

// Clear filament assign requests
_assignFilaments = false;
lock (_extruderFilamentMapping)
{
_extruderFilamentMapping.Clear();
}

// Clear messages to send to the firmware
lock (_messagesToSend)
{
_messagesToSend.Clear();
}

// Notify the updater task
Model.Updater.ConnectionLost();

Expand Down

0 comments on commit a5d8b28

Please sign in to comment.