Made the unloading wizard code rather than macro

Took out the macro processing stream
This commit is contained in:
Lars Brubaker 2018-11-05 11:08:21 -08:00
parent c13b757c0c
commit 734bd88c86
14 changed files with 285 additions and 622 deletions

View file

@ -54,12 +54,12 @@ namespace MatterHackers.MatterControl.ActionBar
this.HAnchor = HAnchor.Stretch;
this.printer = printer;
GuiWidget macroButtons = null;
GuiWidget loadUnloadButtons = null;
// We do not yet support loading filament into extruders other than 0, fix it when time.
if (extruderIndex == 0)
{
// add in load and unload buttons
macroButtons = new FlowLayoutWidget()
loadUnloadButtons = new FlowLayoutWidget()
{
Padding = theme.ToolbarPadding,
};
@ -74,19 +74,20 @@ namespace MatterHackers.MatterControl.ActionBar
LoadFilamentWizard.Start(printer, theme, true);
});
};
macroButtons.AddChild(loadButton);
var unloadFilament = new GCodeMacro()
{
GCode = AggContext.StaticData.ReadAllText(Path.Combine("SliceSettings", "unload_filament.txt"))
};
loadUnloadButtons.AddChild(loadButton);
var unloadButton = theme.CreateDialogButton("Unload".Localize());
unloadButton.ToolTipText = "Unload filament".Localize();
unloadButton.Click += (s, e) => unloadFilament.Run(printer.Connection);
macroButtons.AddChild(unloadButton);
unloadButton.Click += (s, e) =>
{
UiThread.RunOnIdle(() =>
{
UnloadFilamentWizard.Start(printer, theme, true);
});
};
loadUnloadButtons.AddChild(unloadButton);
this.AddChild(new SettingsItem("Filament".Localize(), macroButtons, theme, enforceGutter: false));
this.AddChild(new SettingsItem("Filament".Localize(), loadUnloadButtons, theme, enforceGutter: false));
}
// Add the Extrude buttons
@ -97,7 +98,7 @@ namespace MatterHackers.MatterControl.ActionBar
Padding = theme.ToolbarPadding,
};
int extruderButtonTopMargin = macroButtons == null ? 8 : 0;
int extruderButtonTopMargin = loadUnloadButtons == null ? 8 : 0;
var extrudeButton = theme.CreateDialogButton("Extrude".Localize());
extrudeButton.Name = "Extrude Button";
@ -117,7 +118,7 @@ namespace MatterHackers.MatterControl.ActionBar
buttonContainer.AddChild(retractButton);
this.AddChild(new SettingsItem(
macroButtons == null ? "Filament".Localize() : "", // Don't put the name if we put in a macro button (it has the name)
loadUnloadButtons == null ? "Filament".Localize() : "", // Don't put the name if we put in a load and unload button (it has the name)
buttonContainer,
theme,
enforceGutter: false));

View file

@ -81,7 +81,7 @@ namespace MatterHackers.MatterControl.ConfigurationPage.PrintLeveling
var instructions = "Please select the material you want to load.".Localize();
// select the material
yield return new SelectMaterialPage(this, title, instructions, onlyLoad);
yield return new SelectMaterialPage(this, title, instructions, "Load".Localize(), onlyLoad);
var theme = ApplicationController.Instance.Theme;
@ -197,6 +197,10 @@ namespace MatterHackers.MatterControl.ConfigurationPage.PrintLeveling
// Allow extrusion at any temperature. S0 only works on Marlin S1 works on repetier and marlin
printer.Connection.QueueLine("M302 S1");
// send a dwel to empty out the current move commands
printer.Connection.QueueLine("G4 P1");
// put in a second one to use as a signal for the first being processed
printer.Connection.QueueLine("G4 P1");
// start heating up the extruder
printer.Connection.SetTargetHotendTemperature(0, printer.Settings.GetValue<double>(SettingsKey.temperature));
@ -205,17 +209,23 @@ namespace MatterHackers.MatterControl.ConfigurationPage.PrintLeveling
var remainingLengthMm = loadLengthMm;
var maxSingleExtrudeLength = 20;
var runningTime = Stopwatch.StartNew();
Stopwatch runningTime = null;
var expectedTimeS = loadLengthMm / loadingSpeedMmPerS;
runningGCodeCommands = UiThread.SetInterval(() =>
{
if (printer.Connection.NumQueuedCommands == 0)
{
if(runningTime == null)
{
runningTime = Stopwatch.StartNew();
}
if (progressBar.RatioComplete < 1)
{
var thisExtrude = Math.Min(remainingLengthMm, maxSingleExtrudeLength);
var currentE = printer.Connection.CurrentExtruderDestination;
printer.Connection.QueueLine("G1 {0}{1:0.###} F{2}".FormatWith(PrinterCommunication.PrinterConnection.Axis.E, currentE + thisExtrude, loadingSpeedMmPerS * 60));
printer.Connection.QueueLine("G1 E{0:0.###} F{1}".FormatWith(currentE + thisExtrude, loadingSpeedMmPerS * 60));
remainingLengthMm -= thisExtrude;
var elapsedSeconds = runningTime.Elapsed.TotalSeconds;
progressBar.RatioComplete = Math.Min(1, elapsedSeconds / expectedTimeS);
@ -223,7 +233,9 @@ namespace MatterHackers.MatterControl.ConfigurationPage.PrintLeveling
}
}
if (progressBar.RatioComplete == 1)
if (runningGCodeCommands.Continue == true
&& progressBar.RatioComplete == 1
&& remainingLengthMm <= .001)
{
runningGCodeCommands.Continue = false;
loadingFilamentPage.NextButton.InvokeClick();
@ -276,8 +288,6 @@ namespace MatterHackers.MatterControl.ConfigurationPage.PrintLeveling
{
BecomingActive = () =>
{
runningCleanPage.ShowWizardFinished();
var markdownText = printer.Settings.GetValue(SettingsKey.running_clean_markdown);
var markdownWidget = new MarkdownWidget(theme);
markdownWidget.Markdown = markdownText = markdownText.Replace("\\n", "\n");
@ -317,6 +327,18 @@ namespace MatterHackers.MatterControl.ConfigurationPage.PrintLeveling
yield return runningCleanPage;
}
// put up a success message
PrinterSetupWizardPage finalPage = null;
finalPage = new PrinterSetupWizardPage(this, "Success".Localize(), "Success!\n\nYour filament should now be loaded".Localize())
{
BecomingActive = () =>
{
finalPage.ShowWizardFinished();
}
};
yield return finalPage;
}
}
}

View file

@ -0,0 +1,212 @@
/*
Copyright (c) 2018, Lars Brubaker, John Lewin
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
The views and conclusions contained in the software and documentation are those
of the authors and should not be interpreted as representing official policies,
either expressed or implied, of the FreeBSD Project.
*/
using System;
using System.Collections.Generic;
using System.Diagnostics;
using Markdig.Agg;
using MatterHackers.Agg;
using MatterHackers.Agg.UI;
using MatterHackers.Localizations;
using MatterHackers.MatterControl.PrinterCommunication;
using MatterHackers.MatterControl.SlicerConfiguration;
namespace MatterHackers.MatterControl.ConfigurationPage.PrintLeveling
{
public class UnloadFilamentWizard : PrinterSetupWizard
{
private bool onlyLoad;
public static void Start(PrinterConfig printer, ThemeConfig theme, bool onlyLoad)
{
// turn off print leveling
var levelingContext = new UnloadFilamentWizard(printer, onlyLoad)
{
WindowTitle = $"{ApplicationController.Instance.ProductName} - " + "Unload Filament Wizard".Localize()
};
var loadFilamentWizardWindow = DialogWindow.Show(new LevelingWizardRootPage(levelingContext)
{
WindowTitle = levelingContext.WindowTitle
});
loadFilamentWizardWindow.Closed += (s, e) =>
{
printer.Connection.TurnOffBedAndExtruders(TurnOff.AfterDelay);
};
}
public UnloadFilamentWizard(PrinterConfig printer, bool onlyLoad)
: base(printer)
{
this.onlyLoad = onlyLoad;
}
protected override IEnumerator<PrinterSetupWizardPage> GetWizardSteps()
{
var levelingStrings = new LevelingStrings(printer.Settings);
var title = "Unload Material".Localize();
var instructions = "Please select the material you want to unload.".Localize();
// select the material
yield return new SelectMaterialPage(this, title, instructions, "Unload".Localize(), onlyLoad);
var theme = ApplicationController.Instance.Theme;
// wait for extruder to heat
{
double targetHotendTemp = printer.Settings.Helpers.ExtruderTemperature(0);
yield return new WaitForTempPage(
this,
"Waiting For Printer To Heat".Localize(),
"Waiting for the hotend to heat to ".Localize() + targetHotendTemp + "°C.\n"
+ "This will ensure that filament is able to flow through the nozzle.".Localize() + "\n"
+ "\n"
+ "Warning! The tip of the nozzle will be HOT!".Localize() + "\n"
+ "Avoid contact with your skin.".Localize(),
0,
targetHotendTemp);
}
// show the unloading filament progress bar
{
RunningInterval runningGCodeCommands = null;
PrinterSetupWizardPage unloadingFilamentPage = null;
unloadingFilamentPage = new PrinterSetupWizardPage(
this,
"Unloading Filament".Localize(),
"")
{
BecomingActive = () =>
{
unloadingFilamentPage.NextButton.Enabled = false;
// add the progress bar
var holder = new FlowLayoutWidget();
var progressBar = new ProgressBar((int)(150 * GuiWidget.DeviceScale), (int)(15 * GuiWidget.DeviceScale))
{
FillColor = theme.PrimaryAccentColor,
BorderColor = theme.TextColor,
BackgroundColor = Color.White,
Margin = new BorderDouble(3, 0, 0, 10),
};
var progressBarText = new TextWidget("", pointSize: 10, textColor: theme.TextColor)
{
AutoExpandBoundsToText = true,
Margin = new BorderDouble(5, 0, 0, 0),
};
holder.AddChild(progressBar);
holder.AddChild(progressBarText);
unloadingFilamentPage.ContentRow.AddChild(holder);
// Allow extrusion at any temperature. S0 only works on Marlin S1 works on repetier and marlin
printer.Connection.QueueLine("M302 S1");
// send a dwel to empty out the current move commands
printer.Connection.QueueLine("G4 P1");
// put in a second one to use as a signal for the first being processed
printer.Connection.QueueLine("G4 P1");
// start heating up the extruder
printer.Connection.SetTargetHotendTemperature(0, printer.Settings.GetValue<double>(SettingsKey.temperature));
var loadingSpeedMmPerS = printer.Settings.GetValue<double>(SettingsKey.load_filament_speed);
var loadLengthMm = Math.Max(1, printer.Settings.GetValue<double>(SettingsKey.unload_filament_length));
var remainingLengthMm = loadLengthMm;
var maxSingleExtrudeLength = 20;
Stopwatch runningTime = null;
var expectedTimeS = loadLengthMm / loadingSpeedMmPerS;
// push some out first
var currentE = printer.Connection.CurrentExtruderDestination;
printer.Connection.QueueLine("G1 E{0:0.###} F600".FormatWith(currentE + 15));
runningGCodeCommands = UiThread.SetInterval(() =>
{
if (printer.Connection.NumQueuedCommands == 0)
{
if (runningTime == null)
{
runningTime = Stopwatch.StartNew();
}
if (progressBar.RatioComplete < 1)
{
var thisExtrude = Math.Min(remainingLengthMm, maxSingleExtrudeLength);
currentE = printer.Connection.CurrentExtruderDestination;
printer.Connection.QueueLine("G1 E{0:0.###} F{1}".FormatWith(currentE - thisExtrude, loadingSpeedMmPerS * 60));
remainingLengthMm -= thisExtrude;
var elapsedSeconds = runningTime.Elapsed.TotalSeconds;
progressBar.RatioComplete = Math.Min(1, elapsedSeconds / expectedTimeS);
progressBarText.Text = $"Unloading Filament: {Math.Max(0, expectedTimeS - elapsedSeconds):0}";
}
}
if (runningGCodeCommands.Continue == true
&& progressBar.RatioComplete == 1
&& remainingLengthMm <= .001)
{
runningGCodeCommands.Continue = false;
unloadingFilamentPage.NextButton.InvokeClick();
}
},
.1);
},
BecomingInactive = () =>
{
if (runningGCodeCommands.Continue)
{
runningGCodeCommands.Continue = false;
}
}
};
unloadingFilamentPage.Closed += (s, e) =>
{
if (runningGCodeCommands.Continue)
{
runningGCodeCommands.Continue = false;
}
};
yield return unloadingFilamentPage;
}
// put up a success message
PrinterSetupWizardPage finalPage = null;
finalPage = new PrinterSetupWizardPage(this, "Success".Localize(), "Success!\n\nYour filament should now be unloaded".Localize())
{
BecomingActive = () =>
{
finalPage.ShowWizardFinished();
}
};
yield return finalPage;
}
}
}

View file

@ -36,7 +36,7 @@ namespace MatterHackers.MatterControl.ConfigurationPage.PrintLeveling
{
public class SelectMaterialPage : PrinterSetupWizardPage
{
public SelectMaterialPage(PrinterSetupWizard context, string headerText, string instructionsText, bool onlyLoad)
public SelectMaterialPage(PrinterSetupWizard context, string headerText, string instructionsText, string nextButtonText, bool onlyLoad)
: base(context, headerText, instructionsText)
{
contentRow.AddChild(
@ -46,7 +46,7 @@ namespace MatterHackers.MatterControl.ConfigurationPage.PrintLeveling
Margin = new BorderDouble(0, 0, 0, 15)
});
NextButton.Text = "Load";
NextButton.Text = nextButtonText;
if (!onlyLoad)
{

View file

@ -1,191 +0,0 @@
/*
Copyright (c) 2018, Lars Brubaker, John Lewin
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
The views and conclusions contained in the software and documentation are those
of the authors and should not be interpreted as representing official policies,
either expressed or implied, of the FreeBSD Project.
*/
using System;
using Markdig.Agg;
using MatterHackers.Agg;
using MatterHackers.Agg.Image;
using MatterHackers.Agg.UI;
using MatterHackers.Localizations;
using MatterHackers.MatterControl.SlicerConfiguration;
namespace MatterHackers.MatterControl.PrinterControls
{
public class RunningMacroPage : DialogPage
{
private long startTimeMs;
private ProgressBar progressBar;
private RunningInterval runningInterval;
private TextWidget progressBarText;
private long timeToWaitMs;
private PrinterConfig printer;
public RunningMacroPage(PrinterConfig printer, MacroCommandData macroData, ThemeConfig theme)
: base("Cancel")
{
this.printer = printer;
this.WindowTitle = "Running Macro".Localize();
this.HeaderText = macroData.title;
if (macroData.showMaterialSelector)
{
contentRow.AddChild(new PresetSelectorWidget(printer, "Material".Localize(), Color.Transparent, NamedSettingsLayers.Material, theme)
{
BackgroundColor = Color.Transparent,
Margin = new BorderDouble(0, 0, 0, 15)
});
}
printer.Connection.LineSent.RegisterEvent(LookForTempRequest, ref unregisterEvents);
if (macroData.waitOk | macroData.expireTime > 0)
{
var okButton = theme.CreateDialogButton("Continue".Localize());
okButton.Name = "Continue Button";
okButton.Click += (s, e) =>
{
ContinueToNextPage = true;
printer.Connection.MacroContinue();
};
this.AddPageAction(okButton);
}
if (!string.IsNullOrEmpty(macroData.markdown))
{
var markdown = new MarkdownWidget(theme);
markdown.Markdown = macroData.markdown;
contentRow.AddChild(markdown);
}
var holder = new FlowLayoutWidget();
progressBar = new ProgressBar((int)(150 * GuiWidget.DeviceScale), (int)(15 * GuiWidget.DeviceScale))
{
FillColor = theme.PrimaryAccentColor,
BorderColor = theme.TextColor,
BackgroundColor = Color.White,
Margin = new BorderDouble(3, 0, 0, 10),
};
progressBarText = new TextWidget("", pointSize: 10, textColor: theme.TextColor)
{
AutoExpandBoundsToText = true,
Margin = new BorderDouble(5, 0, 0, 0),
};
holder.AddChild(progressBar);
holder.AddChild(progressBarText);
contentRow.AddChild(holder);
progressBar.Visible = false;
if (macroData.countDown > 0)
{
timeToWaitMs = (long)(macroData.countDown * 1000);
startTimeMs = UiThread.CurrentTimerMs;
runningInterval = UiThread.SetInterval(CountDownTime, .2);
}
}
protected override void OnCancel(out bool abortCancel)
{
printer.Connection.MacroCancel();
abortCancel = false;
}
private EventHandler unregisterEvents;
public class MacroCommandData
{
public bool waitOk = false;
public string title = "";
public bool showMaterialSelector = false;
public double countDown = 0;
public double expireTime = 0;
public double expectedTemperature = 0;
public string markdown = "";
}
public override void OnClosed(EventArgs e)
{
if (!ContinueToNextPage)
{
printer.Connection.MacroCancel();
}
unregisterEvents?.Invoke(this, null);
base.OnClosed(e);
}
private void CountDownTime()
{
if(runningInterval != null)
{
runningInterval.Continue = !HasBeenClosed && progressBar.RatioComplete < 1;
if(!runningInterval.Continue)
{
ContinueToNextPage = true;
}
}
progressBar.Visible = true;
long timeSinceStartMs = UiThread.CurrentTimerMs - startTimeMs;
progressBar.RatioComplete = timeToWaitMs == 0 ? 1 : Math.Max(0, Math.Min(1, ((double)timeSinceStartMs / (double)timeToWaitMs)));
int seconds = (int)((timeToWaitMs - (timeToWaitMs * (progressBar.RatioComplete))) / 1000);
progressBarText.Text = $"Time Remaining: {seconds / 60:#0}:{seconds % 60:00}";
}
double startingTemp;
public bool ContinueToNextPage { get; set; } = false;
private void LookForTempRequest(object sender, EventArgs e)
{
var stringEvent = e as StringEventArgs;
if(stringEvent != null
&& stringEvent.Data.Contains("M104"))
{
startingTemp = printer.Connection.GetActualHotendTemperature(0);
RunningInterval runningInterval = null;
runningInterval = UiThread.SetInterval(() =>
{
runningInterval.Continue = !HasBeenClosed && progressBar.RatioComplete < 1;
progressBar.Visible = true;
double targetTemp = printer.Connection.GetTargetHotendTemperature(0);
double actualTemp = printer.Connection.GetActualHotendTemperature(0);
double totalDelta = targetTemp - startingTemp;
double currentDelta = actualTemp - startingTemp;
double ratioDone = totalDelta != 0 ? (currentDelta / totalDelta) : 1;
progressBar.RatioComplete = Math.Min(Math.Max(0, ratioDone), 1);
progressBarText.Text = $"Temperature: {actualTemp:0} / {targetTemp:0}";
}, 1);
}
}
}
}

View file

@ -1,304 +0,0 @@
/*
Copyright (c) 2015, Lars Brubaker
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
The views and conclusions contained in the software and documentation are those
of the authors and should not be interpreted as representing official policies,
either expressed or implied, of the FreeBSD Project.
*/
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Text.RegularExpressions;
using System.Threading;
using MatterHackers.Agg.Image;
using MatterHackers.Agg.Platform;
using MatterHackers.Agg.UI;
using MatterHackers.MatterControl.PrinterControls;
using MatterHackers.MatterControl.SlicerConfiguration;
namespace MatterHackers.MatterControl.PrinterCommunication.Io
{
public class MacroProcessingStream : GCodeStreamProxy
{
public const string MacroPrefix = "; host.";
private List<string> commandsToRepeat = new List<string>();
private object locker = new object();
private double maxTimeToWaitForOk = 0;
private int repeatCommandIndex = 0;
private bool runningMacro = false;
private double startingBedTemp = 0;
private List<double> startingExtruderTemps = new List<double>();
private Stopwatch timeHaveBeenWaiting = new Stopwatch();
private bool WaitingForUserInput { get; set; } = false;
private PrinterConfig printer;
QueuedCommandsStream queuedCommandsStream;
RunningMacroPage currentPage = null;
public MacroProcessingStream(QueuedCommandsStream queuedCommandsStream, PrinterConfig printer)
: base(queuedCommandsStream)
{
this.queuedCommandsStream = queuedCommandsStream;
this.printer = printer;
}
public void Cancel()
{
Reset();
}
public void Continue()
{
WaitingForUserInput = false;
timeHaveBeenWaiting.Reset();
maxTimeToWaitForOk = 0;
commandsToRepeat.Clear();
}
public static ImageBuffer LoadImageAsset(string uri)
{
string filePath = Path.Combine("Images", "Macros", uri);
bool imageOnDisk = false;
if (uri.IndexOfAny(Path.GetInvalidFileNameChars()) == -1)
{
try
{
imageOnDisk = AggContext.StaticData.FileExists(filePath);
}
catch
{
imageOnDisk = false;
}
}
if (imageOnDisk)
{
return AggContext.StaticData.LoadImage(filePath);
}
else
{
var imageBuffer = new ImageBuffer(320, 10);
ApplicationController.Instance.DownloadToImageAsync(imageBuffer, uri, true);
return imageBuffer;
}
}
public override string ReadLine()
{
string lineToSend = null;
if (WaitingForUserInput)
{
lineToSend = "";
Thread.Sleep(100);
if (timeHaveBeenWaiting.IsRunning
&& timeHaveBeenWaiting.Elapsed.TotalSeconds > maxTimeToWaitForOk)
{
if (commandsToRepeat.Count > 0)
{
// We timed out without the user responding. Cancel the operation.
Reset();
}
else
{
// everything normal continue after time waited
Continue();
}
}
if (maxTimeToWaitForOk > 0
&& timeHaveBeenWaiting.Elapsed.TotalSeconds < maxTimeToWaitForOk
&& commandsToRepeat.Count > 0)
{
lineToSend = commandsToRepeat[repeatCommandIndex % commandsToRepeat.Count];
repeatCommandIndex++;
}
}
else
{
lineToSend = base.ReadLine();
if (!string.IsNullOrEmpty(lineToSend))
{
if (lineToSend.StartsWith(MacroPrefix) && lineToSend.TrimEnd().EndsWith(")"))
{
if (!runningMacro)
{
runningMacro = true;
int extruderCount = printer.Settings.GetValue<int>(SettingsKey.extruder_count);
for (int i = 0; i < extruderCount; i++)
{
startingExtruderTemps.Add(printer.Connection.GetTargetHotendTemperature(i));
}
if (printer.Settings.GetValue<bool>(SettingsKey.has_heated_bed))
{
startingBedTemp = printer.Connection.TargetBedTemperature;
}
}
int parensAfterCommand = lineToSend.IndexOf('(', MacroPrefix.Length);
string command = "";
if (parensAfterCommand > 0)
{
command = lineToSend.Substring(MacroPrefix.Length, parensAfterCommand - MacroPrefix.Length);
}
RunningMacroPage.MacroCommandData macroData = new RunningMacroPage.MacroCommandData();
string value = "";
if (TryGetAfterString(lineToSend, "title", out value))
{
macroData.title = value;
}
if (TryGetAfterString(lineToSend, "expire", out value))
{
double.TryParse(value, out macroData.expireTime);
maxTimeToWaitForOk = macroData.expireTime;
timeHaveBeenWaiting.Restart();
}
if (TryGetAfterString(lineToSend, "count_down", out value))
{
double.TryParse(value, out macroData.countDown);
}
if (TryGetAfterString(lineToSend, "markdown", out value))
{
// change writen \n's to actual cr.
var processedText = value.Replace("\\n", "\n");
// turn <br> into cr so we have more control
processedText = processedText.Replace("<br>", "\n");
macroData.markdown = processedText;
}
if (TryGetAfterString(lineToSend, "wait_ok", out value))
{
macroData.waitOk = value == "true";
}
if (TryGetAfterString(lineToSend, "repeat_gcode", out value))
{
foreach (string line in value.Split('|'))
{
commandsToRepeat.Add(line);
}
}
switch (command)
{
case "choose_material":
WaitingForUserInput = true;
macroData.showMaterialSelector = true;
macroData.waitOk = true;
UiThread.RunOnIdle(() =>
{
// we are continuing normaly
if (currentPage != null)
{
currentPage.ContinueToNextPage = true;
}
DialogWindow.Show(currentPage = new RunningMacroPage(printer, macroData, ApplicationController.Instance.Theme));
});
break;
case "close":
runningMacro = false;
// we are closing normaly
if (currentPage != null)
{
currentPage.ContinueToNextPage = true;
}
UiThread.RunOnIdle(() => DialogWindow.Close(typeof(RunningMacroPage)));
break;
case "ding":
AppContext.Platform.PlaySound("timer-done.wav");
break;
case "done_load_unload":
if (!printer.Connection.PrinterIsPrinting
&& !printer.Connection.PrinterIsPaused)
{
// turn off the temps
printer.Connection.TurnOffBedAndExtruders(TurnOff.AfterDelay);
}
break;
case "show_message":
WaitingForUserInput = macroData.waitOk | macroData.expireTime > 0;
UiThread.RunOnIdle(() =>
{
// we are continuing normaly
if (currentPage != null)
{
currentPage.ContinueToNextPage = true;
}
DialogWindow.Show(currentPage = new RunningMacroPage(printer, macroData, ApplicationController.Instance.Theme));
});
break;
default:
// Don't know the command. Print to terminal log?
break;
}
}
}
}
return lineToSend;
}
public void Reset()
{
if (runningMacro)
{
runningMacro = false;
for (int i = 0; i < startingExtruderTemps.Count; i++)
{
printer.Connection.SetTargetHotendTemperature(i, startingExtruderTemps[i]);
}
if (printer.Settings.GetValue<bool>(SettingsKey.has_heated_bed))
{
printer.Connection.TargetBedTemperature = startingBedTemp;
}
}
WaitingForUserInput = false;
timeHaveBeenWaiting.Reset();
maxTimeToWaitForOk = 0;
UiThread.RunOnIdle(() => DialogWindow.Close(typeof(RunningMacroPage)));
}
private bool TryGetAfterString(string macroLine, string variableName, out string value)
{
var macroMatch = Regex.Match(macroLine, variableName + ":\"([^\"]+)");
value = macroMatch.Success ? macroMatch.Groups[1].Value : null;
return macroMatch.Success;
}
}
}

View file

@ -187,15 +187,14 @@ namespace MatterHackers.MatterControl.PrinterCommunication
private SendProgressStream sendProgressStream1 = null;
private PauseHandlingStream pauseHandlingStream2 = null;
private QueuedCommandsStream queuedCommandStream3 = null;
private MacroProcessingStream macroProcessingStream4 = null;
private RelativeToAbsoluteStream relativeToAbsoluteStream5 = null;
private PrintLevelingStream printLevelingStream7 = null;
private WaitForTempStream waitForTempStream8 = null;
private BabyStepsStream babyStepsStream6 = null;
private ExtrusionMultiplyerStream extrusionMultiplyerStream9 = null;
private FeedRateMultiplyerStream feedrateMultiplyerStream10 = null;
private RequestTemperaturesStream requestTemperaturesStream11 = null;
private ProcessWriteRegexStream processWriteRegExStream12 = null;
private RelativeToAbsoluteStream relativeToAbsoluteStream4 = null;
private BabyStepsStream babyStepsStream5 = null;
private PrintLevelingStream printLevelingStream6 = null;
private WaitForTempStream waitForTempStream7 = null;
private ExtrusionMultiplyerStream extrusionMultiplyerStream8 = null;
private FeedRateMultiplyerStream feedrateMultiplyerStream9 = null;
private RequestTemperaturesStream requestTemperaturesStream10 = null;
private ProcessWriteRegexStream processWriteRegExStream11 = null;
private GCodeStream totalGCodeStream = null;
@ -2129,25 +2128,24 @@ namespace MatterHackers.MatterControl.PrinterCommunication
}
queuedCommandStream3 = new QueuedCommandsStream(firstStreamToRead);
macroProcessingStream4 = new MacroProcessingStream(queuedCommandStream3, printer);
relativeToAbsoluteStream5 = new RelativeToAbsoluteStream(macroProcessingStream4);
relativeToAbsoluteStream4 = new RelativeToAbsoluteStream(queuedCommandStream3);
bool enableLineSpliting = gcodeFilename != null && printer.Settings.GetValue<bool>(SettingsKey.enable_line_splitting);
babyStepsStream6 = new BabyStepsStream(printer, relativeToAbsoluteStream5, enableLineSpliting ? 1 : 2000);
babyStepsStream5 = new BabyStepsStream(printer, relativeToAbsoluteStream4, enableLineSpliting ? 1 : 2000);
if (activePrintTask != null)
{
// make sure we are in the position we were when we stopped printing
babyStepsStream6.Offset = new Vector3(activePrintTask.PrintingOffsetX, activePrintTask.PrintingOffsetY, activePrintTask.PrintingOffsetZ);
babyStepsStream5.Offset = new Vector3(activePrintTask.PrintingOffsetX, activePrintTask.PrintingOffsetY, activePrintTask.PrintingOffsetZ);
}
printLevelingStream7 = new PrintLevelingStream(printer, babyStepsStream6, true);
waitForTempStream8 = new WaitForTempStream(this, printLevelingStream7);
extrusionMultiplyerStream9 = new ExtrusionMultiplyerStream(waitForTempStream8);
feedrateMultiplyerStream10 = new FeedRateMultiplyerStream(extrusionMultiplyerStream9);
requestTemperaturesStream11 = new RequestTemperaturesStream(this, feedrateMultiplyerStream10);
processWriteRegExStream12 = new ProcessWriteRegexStream(printer, requestTemperaturesStream11, queuedCommandStream3);
totalGCodeStream = processWriteRegExStream12;
printLevelingStream6 = new PrintLevelingStream(printer, babyStepsStream5, true);
waitForTempStream7 = new WaitForTempStream(this, printLevelingStream6);
extrusionMultiplyerStream8 = new ExtrusionMultiplyerStream(waitForTempStream7);
feedrateMultiplyerStream9 = new FeedRateMultiplyerStream(extrusionMultiplyerStream8);
requestTemperaturesStream10 = new RequestTemperaturesStream(this, feedrateMultiplyerStream9);
processWriteRegExStream11 = new ProcessWriteRegexStream(printer, requestTemperaturesStream10, queuedCommandStream3);
totalGCodeStream = processWriteRegExStream11;
// Force a reset of the printer checksum state (but allow it to be write regexed)
var transformedCommand = processWriteRegExStream12?.ProcessWriteRegEx("M110 N1");
var transformedCommand = processWriteRegExStream11?.ProcessWriteRegEx("M110 N1");
if (transformedCommand != null)
{
foreach (var line in transformedCommand)
@ -2180,13 +2178,13 @@ namespace MatterHackers.MatterControl.PrinterCommunication
// Only update the amount done if it is greater than what is recorded.
// We don't want to mess up the resume before we actually resume it.
if (activePrintTask != null
&& babyStepsStream6 != null
&& babyStepsStream5 != null
&& activePrintTask.PercentDone < currentDone)
{
activePrintTask.PercentDone = currentDone;
activePrintTask.PrintingOffsetX = (float)babyStepsStream6.Offset.X;
activePrintTask.PrintingOffsetY = (float)babyStepsStream6.Offset.Y;
activePrintTask.PrintingOffsetZ = (float)babyStepsStream6.Offset.Z;
activePrintTask.PrintingOffsetX = (float)babyStepsStream5.Offset.X;
activePrintTask.PrintingOffsetY = (float)babyStepsStream5.Offset.Y;
activePrintTask.PrintingOffsetZ = (float)babyStepsStream5.Offset.Z;
activePrintTask?.Commit();
// Interval looks to be ~10ms
@ -2277,13 +2275,13 @@ namespace MatterHackers.MatterControl.PrinterCommunication
timeSinceStartedPrint.Stop();
DetailedPrintingState = DetailedPrintingState.HomingAxis;
}
else if (waitForTempStream8?.HeatingBed ?? false)
else if (waitForTempStream7?.HeatingBed ?? false)
{
// don't time the heating bed opperation opperation
timeSinceStartedPrint.Stop();
DetailedPrintingState = DetailedPrintingState.HeatingBed;
}
else if (waitForTempStream8?.HeatingExtruder ?? false)
else if (waitForTempStream7?.HeatingExtruder ?? false)
{
// don't time the heating extruder opperation opperation
timeSinceStartedPrint.Stop();
@ -2659,20 +2657,13 @@ namespace MatterHackers.MatterControl.PrinterCommunication
public void MacroStart()
{
queuedCommandStream3?.Reset();
macroProcessingStream4.Reset();
}
public void MacroCancel()
{
babyStepsStream6?.CancelMoves();
waitForTempStream8?.Cancel();
babyStepsStream5?.CancelMoves();
waitForTempStream7?.Cancel();
queuedCommandStream3?.Cancel();
macroProcessingStream4?.Cancel();
}
public void MacroContinue()
{
macroProcessingStream4?.Continue();
}
public class ReadThread

View file

@ -60,10 +60,6 @@ namespace MatterHackers.MatterControl.SlicerConfiguration
{
printerConnection.MacroStart();
printerConnection.QueueLine(GCode);
if (GCode.Contains(MacroProcessingStream.MacroPrefix))
{
printerConnection.QueueLine("\n" + MacroProcessingStream.MacroPrefix + "close()");
}
}
}
}

View file

@ -152,6 +152,7 @@ namespace MatterHackers.MatterControl.SlicerConfiguration
public const string temperature3 = nameof(temperature3);
public const string top_solid_infill_speed = nameof(top_solid_infill_speed);
public const string trim_filament_markdown = nameof(trim_filament_markdown);
public const string unload_filament_length = nameof(unload_filament_length);
public const string use_z_probe = nameof(use_z_probe);
public const string validate_layer_height = nameof(validate_layer_height);
public const string windows_driver = nameof(windows_driver);

View file

@ -119,7 +119,7 @@ namespace MatterHackers.MatterControl.SlicerConfiguration
SettingsKey.trim_filament_markdown,
SettingsKey.insert_filament_markdown,
SettingsKey.running_clean_markdown,
"unload_filament_length",
SettingsKey.unload_filament_length,
SettingsKey.load_filament_speed,
};

View file

@ -55,7 +55,6 @@ namespace MatterHackers.MatterControl.SlicerConfiguration
new MappedSetting(SettingsKey.max_fan_speed,"max_fan_speed"),
new MappedSetting(SettingsKey.min_fan_speed,"min_fan_speed"),
new MappedSetting("retract_length","retract_length"),
new LoadTimeFromSpeedAndLength("unload_filament_time", "unload_filament_length", SettingsKey.load_filament_speed),
new MappedSetting(SettingsKey.temperature,SettingsKey.temperature),
new MappedSetting("z_offset","z_offset"),
new MappedSetting(SettingsKey.bed_temperature,SettingsKey.bed_temperature),
@ -65,7 +64,6 @@ namespace MatterHackers.MatterControl.SlicerConfiguration
new ScaledSingleNumber("retract_speed","retract_speed", 60),
new ScaledSingleNumber("support_material_speed","support_material_speed", 60),
new ScaledSingleNumber("travel_speed", "travel_speed", 60),
new AsPercentOfReferenceOrDirect("unload_filament_length_over_six", "", "unload_filament_length", 1.0/6.0, false),
new ScaledSingleNumber(SettingsKey.load_filament_speed, SettingsKey.load_filament_speed, 60),
new MappedSetting(SettingsKey.trim_filament_markdown, SettingsKey.trim_filament_markdown),
new MappedSetting(SettingsKey.insert_filament_markdown, SettingsKey.insert_filament_markdown),
@ -664,31 +662,4 @@ namespace MatterHackers.MatterControl.SlicerConfiguration
}
}
}
public class LoadTimeFromSpeedAndLength : MappedSetting
{
string lengthSettingName;
string speedSettingName;
public LoadTimeFromSpeedAndLength(string canonicalSettingsName, string lengthSettingName, string speedSettingName)
: base(canonicalSettingsName, "")
{
this.lengthSettingName = lengthSettingName;
this.speedSettingName = speedSettingName;
}
public override string Value
{
get
{
string lengthString = printer.Settings.GetValue(lengthSettingName);
double length = ParseDouble(lengthString);
string speedString = printer.Settings.GetValue(speedSettingName);
double speed = ParseDouble(speedString);
return (length / speed).ToString();
}
}
}
}