diff --git a/PrinterCommunication/Io/QueuedCommandsStream.cs b/PrinterCommunication/Io/QueuedCommandsStream.cs index 13d05aba1..c27d5466b 100644 --- a/PrinterCommunication/Io/QueuedCommandsStream.cs +++ b/PrinterCommunication/Io/QueuedCommandsStream.cs @@ -59,12 +59,19 @@ namespace MatterHackers.MatterControl.PrinterCommunication.Io { } - public void Add(string line) + public void Add(string line, bool forceTopOfQueue = false) { // lock queue lock (locker) { - commandQueue.Add(line); + if (forceTopOfQueue) + { + commandQueue.Insert(0, line); + } + else + { + commandQueue.Add(line); + } } } diff --git a/PrinterCommunication/Io/RequestTemperaturesStream.cs b/PrinterCommunication/Io/RequestTemperaturesStream.cs index 3dc77d848..1b4adb3d9 100644 --- a/PrinterCommunication/Io/RequestTemperaturesStream.cs +++ b/PrinterCommunication/Io/RequestTemperaturesStream.cs @@ -44,7 +44,8 @@ namespace MatterHackers.MatterControl.PrinterCommunication.Io public override string ReadLine() { - if (nextReadTimeMs < UiThread.CurrentTimerMs + if (!PrinterConnectionAndCommunication.Instance.WatingForPositionRead + && nextReadTimeMs < UiThread.CurrentTimerMs && PrinterConnectionAndCommunication.Instance.PrinterIsConnected) { nextReadTimeMs = UiThread.CurrentTimerMs + 1000; diff --git a/PrinterCommunication/PrinterConnectionAndCommunication.cs b/PrinterCommunication/PrinterConnectionAndCommunication.cs index 79ff3a462..7424448f4 100644 --- a/PrinterCommunication/PrinterConnectionAndCommunication.cs +++ b/PrinterCommunication/PrinterConnectionAndCommunication.cs @@ -27,14 +27,6 @@ of the authors and should not be interpreted as representing official policies, either expressed or implied, of the FreeBSD Project. */ -using System; -using System.Diagnostics; -using System.Globalization; -using System.IO; -using System.Linq; -using System.Runtime.InteropServices; -using System.Threading; -using System.Threading.Tasks; using Gaming.Game; using MatterHackers.Agg; using MatterHackers.Agg.UI; @@ -50,6 +42,14 @@ using MatterHackers.SerialPortCommunication; using MatterHackers.SerialPortCommunication.FrostedSerial; using MatterHackers.VectorMath; using Microsoft.Win32.SafeHandles; +using System; +using System.Diagnostics; +using System.Globalization; +using System.IO; +using System.Linq; +using System.Runtime.InteropServices; +using System.Threading; +using System.Threading.Tasks; namespace MatterHackers.MatterControl.PrinterCommunication { @@ -113,6 +113,8 @@ namespace MatterHackers.MatterControl.PrinterCommunication public RootedObjectEventHandler WroteLine = new RootedObjectEventHandler(); + public bool WatingForPositionRead { get { return waitingForPosition.IsRunning || PositionReadQueued; } } + public RootedObjectEventHandler AtxPowerStateChanged = new RootedObjectEventHandler(); private bool atxPowerIsOn = false; @@ -123,7 +125,7 @@ namespace MatterHackers.MatterControl.PrinterCommunication private static PrinterConnectionAndCommunication globalInstance; - object locker = new object(); + private object locker = new object(); private readonly int JoinThreadTimeoutMs = 5000; @@ -175,7 +177,7 @@ namespace MatterHackers.MatterControl.PrinterCommunication private PrinterMove lastReportedPosition; - DataViewGraph sendTimeAfterOkGraph; + private DataViewGraph sendTimeAfterOkGraph; private GCodeFile loadedGCode = new GCodeFileLoaded(); @@ -227,6 +229,7 @@ namespace MatterHackers.MatterControl.PrinterCommunication private double totalSdBytes = 0; + private bool PositionReadQueued { get; set; } = false; private Stopwatch waitingForPosition = new Stopwatch(); private FoundStringContainsCallbacks WriteLineContainsCallBacks = new FoundStringContainsCallbacks(); @@ -272,6 +275,7 @@ namespace MatterHackers.MatterControl.PrinterCommunication ReadLineStartCallBacks.AddCallbackToKey("EXTENSIONS:", PrinterStatesExtensions); #region hardware failure callbacks + // smoothie temperature failures ReadLineContainsCallBacks.AddCallbackToKey("T:inf", PrinterReportsError); ReadLineContainsCallBacks.AddCallbackToKey("B:inf", PrinterReportsError); @@ -292,7 +296,8 @@ namespace MatterHackers.MatterControl.PrinterCommunication // s3g temperature failures ReadLineContainsCallBacks.AddCallbackToKey("Bot is Shutdown due to Overheat", PrinterReportsError); - #endregion + + #endregion hardware failure callbacks WriteLineStartCallBacks.AddCallbackToKey("M104", ExtruderTemperatureWasWritenToPrinter); WriteLineStartCallBacks.AddCallbackToKey("M109", ExtruderTemperatureWasWritenToPrinter); @@ -321,7 +326,6 @@ namespace MatterHackers.MatterControl.PrinterCommunication feedRateRatio = ActiveSliceSettings.Instance.GetValue(SettingsKey.feedrate_ratio); } }, ref unregisterEvents); - } private void ExtruderIndexSet(object sender, EventArgs e) @@ -451,7 +455,6 @@ namespace MatterHackers.MatterControl.PrinterCommunication TurnOffBedAndExtruders(); for (int extruderIndex = 0; extruderIndex < MAX_EXTRUDERS; extruderIndex++) { - actualExtruderTemperature[extruderIndex] = 0; OnExtruderTemperatureRead(new TemperatureEventArgs(extruderIndex, GetActualExtruderTemperature(extruderIndex))); } @@ -993,8 +996,8 @@ namespace MatterHackers.MatterControl.PrinterCommunication if (ActivePrinter != null) { // Start the process of requesting permission and exit if permission is not currently granted - if (!ActiveSliceSettings.Instance.GetValue(SettingsKey.enable_network_printing) - && !FrostedSerialPort.EnsureDeviceAccess()) + if (!ActiveSliceSettings.Instance.GetValue(SettingsKey.enable_network_printing) + && !FrostedSerialPort.EnsureDeviceAccess()) { CommunicationState = CommunicationStates.FailedToConnect; return; @@ -1162,7 +1165,6 @@ namespace MatterHackers.MatterControl.PrinterCommunication return actualExtruderTemperature[extruderIndex0Based]; } - public double GetTargetExtruderTemperature(int extruderIndex0Based) { extruderIndex0Based = Math.Min(extruderIndex0Based, MAX_EXTRUDERS - 1); @@ -1248,16 +1250,15 @@ namespace MatterHackers.MatterControl.PrinterCommunication public void OnCommunicationStateChanged(EventArgs e) { - CommunicationStateChanged.CallEvents(this, e); #if __ANDROID__ - //Path to the printer output file + //Path to the printer output file string pathToPrintOutputFile = Path.Combine(ApplicationDataStorage.Instance.PublicDataStoragePath, "print_output.txt"); if (CommunicationState == CommunicationStates.FinishedPrint) { - //Only write to the text file if file exists + //Only write to the text file if file exists if (File.Exists(pathToPrintOutputFile)) { Task.Run(() => @@ -1420,7 +1421,8 @@ namespace MatterHackers.MatterControl.PrinterCommunication } } - bool haveReportedError = false; + private bool haveReportedError = false; + public void PrinterReportsError(object sender, EventArgs e) { if (!haveReportedError) @@ -1510,7 +1512,7 @@ namespace MatterHackers.MatterControl.PrinterCommunication public void ArduinoDtrReset() { // TODO: Ideally we would shutdown the printer connection when this method is called and we're connected. The - // current approach results in unpredictable behavior if the caller fails to close the connection + // current approach results in unpredictable behavior if the caller fails to close the connection if (serialPort == null && this.ActivePrinter != null) { IFrostedSerialPort resetSerialPort = FrostedSerialPortFactory.GetAppropriateFactory(this.DriverType).Create(this.ComPort); @@ -1685,7 +1687,8 @@ namespace MatterHackers.MatterControl.PrinterCommunication public void ReadPosition() { - SendLineToPrinterNow("M114"); + SendLineToPrinterNow("M114", true); + PositionReadQueued = true; } public void ReadSdProgress(object sender, EventArgs e) @@ -1728,6 +1731,7 @@ namespace MatterHackers.MatterControl.PrinterCommunication waitingForPosition.Stop(); waitingForPosition.Reset(); + PositionReadQueued = false; } public static void ParseTemperatureString(string temperatureString, @@ -1924,7 +1928,7 @@ namespace MatterHackers.MatterControl.PrinterCommunication } } - public void SendLineToPrinterNow(string lineToWrite) + public void SendLineToPrinterNow(string lineToWrite, bool forceTopOfQueue = false) { lock (locker) { @@ -1956,7 +1960,7 @@ namespace MatterHackers.MatterControl.PrinterCommunication if (lineToWrite.Trim().Length > 0) { // insert the command into the printing queue at the head - InjectGCode(lineToWrite); + InjectGCode(lineToWrite, forceTopOfQueue); } } } @@ -1965,7 +1969,7 @@ namespace MatterHackers.MatterControl.PrinterCommunication public bool SerialPortIsAvailable(string portName) //Check is serial port is in the list of available serial ports { - if(IsNetworkPrinting()) + if (IsNetworkPrinting()) { return true; } @@ -2017,6 +2021,7 @@ namespace MatterHackers.MatterControl.PrinterCommunication PrintWasCanceled = false; waitingForPosition.Reset(); + PositionReadQueued = false; ClearQueuedGCode(); activePrintTask = printTaskToUse; @@ -2144,7 +2149,7 @@ namespace MatterHackers.MatterControl.PrinterCommunication } } - public void SuppressEcho(object sender, EventArgs e) + public void SuppressEcho(object sender, EventArgs e) { FoundStringEventArgs foundStringEventArgs = e as FoundStringEventArgs; foundStringEventArgs.SendToDelegateFunctions = false; @@ -2327,14 +2332,14 @@ namespace MatterHackers.MatterControl.PrinterCommunication PrintingCanContinue(this, null); } - private void InjectGCode(string codeToInject) + private void InjectGCode(string codeToInject, bool forceTopOfQueue = false) { codeToInject = codeToInject.Replace("\\n", "\n"); string[] lines = codeToInject.Split('\n'); for (int i = 0; i < lines.Length; i++) { - queuedCommandStream2?.Add(lines[i]); + queuedCommandStream2?.Add(lines[i], forceTopOfQueue); } } @@ -2371,7 +2376,7 @@ namespace MatterHackers.MatterControl.PrinterCommunication } } - void CreateStreamProcessors(string gcodeFilename, bool recoveryEnabled) + private void CreateStreamProcessors(string gcodeFilename, bool recoveryEnabled) { totalGCodeStream?.Dispose(); @@ -2635,12 +2640,23 @@ namespace MatterHackers.MatterControl.PrinterCommunication } } - string currentSentLine; - string previousSentLine; + private string currentSentLine; + private string previousSentLine; + + private int ExpectedWaitSeconds(string lastInstruction) + { + if (lastInstruction.Contains("G0 ") || lastInstruction.Contains("G1 ")) + { + // for moves we wait only as much as 2 seconds + return 2; + } + + return 10; + } private void TryWriteNextLineFromGCodeFile() { - if(totalGCodeStream == null) + if (totalGCodeStream == null) { // don't try to write until we are initialized return; @@ -2654,21 +2670,11 @@ namespace MatterHackers.MatterControl.PrinterCommunication // we are still sending commands if (currentSentLine != null) { - // the last instruction was a move - string lastInstruction = previousSentLine; - double epectedSecondsToWait = 2; - double maxSecondsToWait = 10; - bool wasMoveAndNoOK = lastInstruction != null - && (lastInstruction.Contains("G0 ") || lastInstruction.Contains("G1 ")) - && timeHaveBeenWaitingForOK.Elapsed.TotalSeconds > epectedSecondsToWait; - bool waitedTooLongForOK = timeHaveBeenWaitingForOK.Elapsed.TotalSeconds > maxSecondsToWait; - // This code is to try and make sure the printer does not stop on transmission errors. // If it has been more than 10 seconds since the printer responded anything // and it was not ok, and it's been more than 30 second since we sent the command. if ((timeSinceLastReadAnything.Elapsed.TotalSeconds > 10 && timeSinceLastWrite.Elapsed.TotalSeconds > 30) - || wasMoveAndNoOK - || waitedTooLongForOK) + || timeHaveBeenWaitingForOK.Elapsed.TotalSeconds > ExpectedWaitSeconds(currentSentLine)) { // Basically we got some response but it did not contain an OK. // The theory is that we may have received a transmission error (like 'OP' rather than 'OK') @@ -2693,7 +2699,7 @@ namespace MatterHackers.MatterControl.PrinterCommunication else { int waitTimeInMs = 60000; // 60 seconds - if (waitingForPosition.IsRunning + if (waitingForPosition.IsRunning && waitingForPosition.ElapsedMilliseconds < waitTimeInMs && PrinterIsConnected) { @@ -2709,7 +2715,7 @@ namespace MatterHackers.MatterControl.PrinterCommunication string[] splitOnSemicolon = currentSentLine.Split(';'); string trimedLine = splitOnSemicolon[0].Trim().ToUpper(); - if (currentSentLine.Contains("M114") + if (trimedLine.Contains("M114") && PrinterIsConnected) { waitingForPosition.Restart(); @@ -2757,7 +2763,7 @@ namespace MatterHackers.MatterControl.PrinterCommunication TurnOffBedAndExtruders(); this.PrintWasCanceled = false; } - else if(communicationState == CommunicationStates.Printing)// we finished printing normally + else if (communicationState == CommunicationStates.Printing)// we finished printing normally { CommunicationState = CommunicationStates.FinishedPrint; @@ -2808,11 +2814,11 @@ namespace MatterHackers.MatterControl.PrinterCommunication } string lineWithChecksum = lineWithCount + "*" + GCodeFile.CalculateChecksum(lineWithCount).ToString(); - + allCheckSumLinesSent.Add(lineWithChecksum); //if ((checkSumCount++ % 11) == 0) - //lineWithChecksum = lineWithCount + "*" + (GCodeFile.CalculateChecksum(lineWithCount) + checkSumCount).ToString(); + //lineWithChecksum = lineWithCount + "*" + (GCodeFile.CalculateChecksum(lineWithCount) + checkSumCount).ToString(); WriteRawToPrinter(lineWithChecksum + "\n", lineToWrite); } @@ -2938,14 +2944,15 @@ namespace MatterHackers.MatterControl.PrinterCommunication queuedCommandStream2?.Continue(); } - bool haveHookedDrawing = false; + private bool haveHookedDrawing = false; public class ReadThread { private static int currentReadThreadIndex = 0; private int creationIndex; - static int numRunning = 0; + private static int numRunning = 0; + public static int NumRunning { get @@ -2954,7 +2961,6 @@ namespace MatterHackers.MatterControl.PrinterCommunication } } - private ReadThread() { numRunning++; @@ -2985,6 +2991,7 @@ namespace MatterHackers.MatterControl.PrinterCommunication { new ReadThread(); } + internal bool IsCurrentThread() { return currentReadThreadIndex == creationIndex; @@ -3049,4 +3056,4 @@ namespace MatterHackers.MatterControl.PrinterCommunication public int Index0Based { get; } public double Temperature { get; } } -} +} \ No newline at end of file diff --git a/Submodules/agg-sharp b/Submodules/agg-sharp index e6553f9bf..fe9c5f482 160000 --- a/Submodules/agg-sharp +++ b/Submodules/agg-sharp @@ -1 +1 @@ -Subproject commit e6553f9bf75a3441f1dead52d9e0bd8a86721d64 +Subproject commit fe9c5f482ab86e3833d9da0f57059c15542449a5 diff --git a/Tests/MatterControl.AutomationTests/LocalLibraryTests.cs b/Tests/MatterControl.AutomationTests/LocalLibraryTests.cs index f8048213d..fede5dc39 100644 --- a/Tests/MatterControl.AutomationTests/LocalLibraryTests.cs +++ b/Tests/MatterControl.AutomationTests/LocalLibraryTests.cs @@ -522,16 +522,17 @@ namespace MatterHackers.MatterControl.Tests.Automation // Click Library Item Print Button testRunner.ClickByName("Row Item Calibration - Box Print Button"); - testRunner.Delay(.5); + testRunner.Delay(2); Assert.AreEqual(initialQueueCount + 1, QueueData.Instance.ItemCount, "Queue count should increment by one after clicking 'Print'"); Assert.AreEqual("Calibration - Box", QueueData.Instance.PrintItems[0].Name, "Library item should be inserted at queue index 0"); Assert.AreEqual("Calibration - Box", QueueData.Instance.SelectedPrintItem.Name, "Library item should be the selected item"); Assert.AreEqual("Calibration - Box", PrinterConnectionAndCommunication.Instance.ActivePrintItem.Name, "PrinterConnectionCommunication item should be the expected item"); - testRunner.ClickByName("Cancel Print Button"); + testRunner.CancelPrint(); + testRunner.Delay(1); - testRunner.WaitForName("Start Print Button", 5); + testRunner.NameExists("Start Print Button"); } return Task.FromResult(0);