From f46aacf5c4905f550351ebda0e595eeb5a01ddde Mon Sep 17 00:00:00 2001 From: John Lewin Date: Sat, 6 Jan 2018 13:26:28 -0800 Subject: [PATCH 1/2] Remove SliceSettings coupling from PrinterConnection - Add properties to PrinterConnection for dependencies in SliceSettings - Set properties on construction - Sync properties on change --- ApplicationView/PrinterModels.cs | 103 +++++++++++++++++ PrinterCommunication/PrinterConnection.cs | 130 ++++++++-------------- 2 files changed, 148 insertions(+), 85 deletions(-) diff --git a/ApplicationView/PrinterModels.cs b/ApplicationView/PrinterModels.cs index a64773078..f60966a56 100644 --- a/ApplicationView/PrinterModels.cs +++ b/ApplicationView/PrinterModels.cs @@ -54,6 +54,7 @@ namespace MatterHackers.MatterControl using System.Collections.Generic; using MatterHackers.MatterControl.PrintLibrary; using MatterHackers.Localizations; + using System.Text.RegularExpressions; public class BedConfig { @@ -617,6 +618,10 @@ namespace MatterHackers.MatterControl public class PrinterConfig { + private static Regex getQuotedParts = new Regex(@"([""'])(\\?.)*?\1", RegexOptions.Compiled); + private string constructedReadRegexString; + private string readRegexString = ""; + public BedConfig Bed { get; } private EventHandler unregisterEvents; @@ -628,7 +633,62 @@ namespace MatterHackers.MatterControl this.Settings = settings; this.Settings.printer = this; + // TODO: ActiveSliceSettings is not our Settings! Move SettingsChanged to instance rather than static ActiveSliceSettings.SettingChanged.RegisterEvent(Printer_SettingChanged, ref unregisterEvents); + + this.Connection.PrintFinished.RegisterEvent((s, e) => + { + // clear single use setting on print completion + foreach (var keyValue in this.Settings.BaseLayer) + { + string currentValue = this.Settings.GetValue(keyValue.Key); + + bool valueIsClear = currentValue == "0" | currentValue == ""; + + SliceSettingData data = SliceSettingsOrganizer.Instance.GetSettingsData(keyValue.Key); + if (data?.ResetAtEndOfPrint == true && !valueIsClear) + { + this.Settings.ClearValue(keyValue.Key); + } + } + }, ref unregisterEvents); + + if (!string.IsNullOrEmpty(this.Settings.GetValue(SettingsKey.baud_rate))) + { + this.Connection.BaudRate = this.Settings.GetValue(SettingsKey.baud_rate); + } + this.Connection.ConnectGCode = this.Settings.GetValue(SettingsKey.connect_gcode); + this.Connection.CancelGCode = this.Settings.GetValue(SettingsKey.cancel_gcode); + this.Connection.EnableNetworkPrinting = this.Settings.GetValue(SettingsKey.enable_network_printing); + this.Connection.AutoReleaseMotors = this.Settings.GetValue(SettingsKey.auto_release_motors); + this.Connection.RecoveryIsEnabled = this.Settings.GetValue(SettingsKey.recover_is_enabled); + this.Connection.ExtruderCount = this.Settings.GetValue(SettingsKey.extruder_count); + this.Connection.SendWithChecksum = this.Settings.GetValue(SettingsKey.send_with_checksum); + + this.ConstructReadReplacements(); + } + + private void ConstructReadReplacements() + { + string readRegex = this.Settings.GetValue(SettingsKey.read_regex); + + if (this.constructedReadRegexString != readRegex) + { + this.constructedReadRegexString = readRegex; + + this.Connection.ReadLineReplacements.Clear(); + + foreach (string regExLine in readRegex.Split(new string[] { "\\n" }, StringSplitOptions.RemoveEmptyEntries)) + { + var matches = getQuotedParts.Matches(regExLine); + if (matches.Count == 2) + { + var search = matches[0].Value.Substring(1, matches[0].Value.Length - 2); + var replace = matches[1].Value.Substring(1, matches[1].Value.Length - 2); + this.Connection.ReadLineReplacements.Add((new Regex(search, RegexOptions.Compiled), replace)); + } + } + } } public PrinterViewState ViewState { get; } = new PrinterViewState(); @@ -748,6 +808,49 @@ namespace MatterHackers.MatterControl this.ReloadSettings(); this.Bed.InvalidateBedMesh(); } + + // Sync settings changes to printer connection + switch(stringEvent.Data) + { + case SettingsKey.feedrate_ratio: + this.Connection.FeedRateRatio = this.Settings.GetValue(SettingsKey.feedrate_ratio); + break; + + case SettingsKey.baud_rate: + if (!string.IsNullOrEmpty(this.Settings.GetValue(SettingsKey.baud_rate))) + { + this.Connection.BaudRate = this.Settings.GetValue(SettingsKey.baud_rate); + } + break; + + case SettingsKey.connect_gcode: + this.Connection.ConnectGCode = this.Settings.GetValue(SettingsKey.connect_gcode); + break; + + case SettingsKey.cancel_gcode: + this.Connection.CancelGCode = this.Settings.GetValue(SettingsKey.cancel_gcode); + break; + + case SettingsKey.enable_network_printing: + this.Connection.EnableNetworkPrinting = this.Settings.GetValue(SettingsKey.enable_network_printing); + break; + + case SettingsKey.auto_release_motors: + this.Connection.AutoReleaseMotors = this.Settings.GetValue(SettingsKey.auto_release_motors); + break; + + case SettingsKey.recover_is_enabled: + this.Connection.RecoveryIsEnabled = this.Settings.GetValue(SettingsKey.recover_is_enabled); + break; + + case SettingsKey.extruder_count: + this.Connection.ExtruderCount = this.Settings.GetValue(SettingsKey.extruder_count); + break; + + case SettingsKey.send_with_checksum: + this.Connection.SendWithChecksum = this.Settings.GetValue(SettingsKey.send_with_checksum); + break; + } } } } diff --git a/PrinterCommunication/PrinterConnection.cs b/PrinterCommunication/PrinterConnection.cs index 29bc72e1f..7d7edce38 100644 --- a/PrinterCommunication/PrinterConnection.cs +++ b/PrinterCommunication/PrinterConnection.cs @@ -1,5 +1,5 @@ /* -Copyright (c) 2014, Lars Brubaker +Copyright (c) 2018, Lars Brubaker, John Lewin All rights reserved. Redistribution and use in source and binary forms, with or without @@ -42,7 +42,6 @@ using MatterControl.Printing; using MatterHackers.Agg; using MatterHackers.MatterControl.DataStorage; using MatterHackers.MatterControl.PrinterCommunication.Io; -using MatterHackers.MatterControl.SlicerConfiguration; using MatterHackers.SerialPortCommunication; using MatterHackers.SerialPortCommunication.FrostedSerial; using MatterHackers.VectorMath; @@ -249,8 +248,6 @@ namespace MatterHackers.MatterControl.PrinterCommunication private EventHandler unregisterEvents; - private double feedRateRatio = 1; - public PrinterConnection(PrinterConfig printer) { this.printer = printer; @@ -272,7 +269,7 @@ namespace MatterHackers.MatterControl.PrinterCommunication ReadLineStartCallBacks.AddCallbackToKey("B:", ReadTemperatures); // smoothie ReadLineContainsCallBacks.AddCallbackToKey("T0:", ReadTemperatures); // marlin - ReadLineContainsCallBacks.AddCallbackToKey("T:", ReadTemperatures); // repatier + ReadLineContainsCallBacks.AddCallbackToKey("T:", ReadTemperatures); // repetier ReadLineStartCallBacks.AddCallbackToKey("SD printing byte", ReadSdProgress); // repetier @@ -328,15 +325,6 @@ namespace MatterHackers.MatterControl.PrinterCommunication WriteLineStartCallBacks.AddCallbackToKey("M140", BedTemperatureWasWritenToPrinter); WriteLineStartCallBacks.AddCallbackToKey("M190", BedTemperatureWasWritenToPrinter); WriteLineStartCallBacks.AddCallbackToKey("T", ExtruderIndexSet); - - ActiveSliceSettings.SettingChanged.RegisterEvent((s, e) => - { - var eventArgs = e as StringEventArgs; - if (eventArgs?.Data == SettingsKey.feedrate_ratio) - { - feedRateRatio = this.printer.Settings.GetValue(SettingsKey.feedrate_ratio); - } - }, ref unregisterEvents); } private void ExtruderIndexSet(object sender, EventArgs e) @@ -361,27 +349,29 @@ namespace MatterHackers.MatterControl.PrinterCommunication } } - public int BaudRate - { - get - { - int baudRate = 250000; - if (this.printer.Settings != null) - { - try - { - if (!string.IsNullOrEmpty(printer.Settings.GetValue(SettingsKey.baud_rate))) - { - baudRate = Convert.ToInt32(printer.Settings.GetValue(SettingsKey.baud_rate)); - } - } - catch - { - } - } - return baudRate; - } - } + // PrinterSettings/Options {{ + + public int BaudRate { get; set; } = 250000; + + public double FeedRateRatio { get; set; } = 1; + + public string ConnectGCode { get; set; } = ""; + + public string CancelGCode { get; set; } = ""; + + public int ExtruderCount { get; set; } + + public bool SendWithChecksum { get; set; } + + public bool EnableNetworkPrinting { get; set; } + + public bool AutoReleaseMotors { get; set; } + + public bool RecoveryIsEnabled { get; set; } + + public List<(Regex Regex, string Replacement)> ReadLineReplacements { get; set; } = new List<(Regex Regex, string Replacement)>(); + + // PrinterSettings/Options }} private bool communicationPossible = false; @@ -473,19 +463,6 @@ namespace MatterHackers.MatterControl.PrinterCommunication communicationState = value; timeSinceStartedPrint.Stop(); PrintFinished.CallEvents(this, new NamedItemEventArgs(printer.Bed.EditContext.SourceItem.Name)); - - // clear single use setting on print completion - foreach (var keyValue in printer.Settings.BaseLayer) - { - string currentValue = printer.Settings.GetValue(keyValue.Key); - - bool valueIsClear = currentValue == "0" | currentValue == ""; - SliceSettingData data = SliceSettingsOrganizer.Instance.GetSettingsData(keyValue.Key); - if (data?.ResetAtEndOfPrint == true && !valueIsClear) - { - printer.Settings.ClearValue(keyValue.Key); - } - } } else { @@ -799,9 +776,9 @@ namespace MatterHackers.MatterControl.PrinterCommunication { if (gCodeFileStream0?.GCodeFile?.LineCount > 0) { - if (feedRateRatio != 0) + if (this.FeedRateRatio != 0) { - return (int)(gCodeFileStream0.GCodeFile.TotalSecondsInPrint / feedRateRatio); + return (int)(gCodeFileStream0.GCodeFile.TotalSecondsInPrint / this.FeedRateRatio); } return (int)(gCodeFileStream0.GCodeFile.TotalSecondsInPrint); @@ -813,6 +790,7 @@ namespace MatterHackers.MatterControl.PrinterCommunication // HACK: PrinterConnection must be revised to take a constructor that receives and stores a reference to its parent PrinterConfig - this private PrinterConfig printer { get; set; } + public string ReadRegex { get; private set; } public void ReleaseAndReportFailedConnection(ConnectionFailure reason, string details = null) { @@ -855,9 +833,10 @@ namespace MatterHackers.MatterControl.PrinterCommunication public void Connect() { + // TODO: Consider adding any conditions that would results in a connection failure to this initial test // Start the process of requesting permission and exit if permission is not currently granted - if (!printer.Settings.GetValue(SettingsKey.enable_network_printing) + if (!this.EnableNetworkPrinting && !FrostedSerialPort.EnsureDeviceAccess()) { // TODO: Consider calling OnConnectionFailed as we do below to fire events that indicate connection failed @@ -981,8 +960,7 @@ namespace MatterHackers.MatterControl.PrinterCommunication TurnOffBedAndExtruders(); // make sure our ui and the printer agree and that the printer is in a known state (not heating). haveReportedError = false; - QueueLine( - printer.Settings.GetValue(SettingsKey.connect_gcode)); + QueueLine(this.ConnectGCode); // Call global event AnyConnectionSucceeded.CallEvents(this, null); @@ -1300,7 +1278,7 @@ namespace MatterHackers.MatterControl.PrinterCommunication { if (currentLineIndexToSend == allCheckSumLinesSent.Count) { - // asking for the next line don't do anything, conitue with sending next instruction + // asking for the next line don't do anything, continue with sending next instruction return; } // smoothie sends an N before the number and no ok @@ -1313,7 +1291,7 @@ namespace MatterHackers.MatterControl.PrinterCommunication if (currentLineIndexToSend == allCheckSumLinesSent.Count) { - // asking for the next line don't do anything, conitue with sending next instruction + // asking for the next line don't do anything, continue with sending next instruction return; } @@ -1712,7 +1690,7 @@ namespace MatterHackers.MatterControl.PrinterCommunication public void ReleaseMotors(bool forceRelease = false) { if (forceRelease - || this.printer.Settings.GetValue(SettingsKey.auto_release_motors)) + || this.AutoReleaseMotors) { QueueLine("M84"); } @@ -1828,32 +1806,13 @@ namespace MatterHackers.MatterControl.PrinterCommunication } #region ProcessRead - private static Regex getQuotedParts = new Regex(@"([""'])(\\?.)*?\1", RegexOptions.Compiled); - private string readRegexString = ""; - private List<(Regex Regex, string Replacement)> ReadLineReplacements = new List<(Regex Regex, string Replacement)>(); + private List addedReadLines = new List(); private string ProcessReadRegEx(string lineBeingRead) { - if (readRegexString != printer.Settings.GetValue(SettingsKey.read_regex)) - { - ReadLineReplacements.Clear(); - string splitString = "\\n"; - readRegexString = printer.Settings.GetValue(SettingsKey.read_regex); - foreach (string regExLine in readRegexString.Split(new string[] { splitString }, StringSplitOptions.RemoveEmptyEntries)) - { - var matches = getQuotedParts.Matches(regExLine); - if (matches.Count == 2) - { - var search = matches[0].Value.Substring(1, matches[0].Value.Length - 2); - var replace = matches[1].Value.Substring(1, matches[1].Value.Length - 2); - ReadLineReplacements.Add((new Regex(search, RegexOptions.Compiled), replace)); - } - } - } - var addedLines = new List(); - foreach (var item in ReadLineReplacements) + foreach (var item in this.ReadLineReplacements) { var splitReplacement = item.Replacement.Split(','); if (splitReplacement.Length > 0) @@ -2020,13 +1979,14 @@ namespace MatterHackers.MatterControl.PrinterCommunication { lock (locker) { + // get rid of all the gcode we have left to print ClearQueuedGCode(); - string cancelGCode = printer.Settings.GetValue(SettingsKey.cancel_gcode); - if (cancelGCode.Trim() != "") + + if (!string.IsNullOrEmpty(this.CancelGCode)) { // add any gcode we want to print while canceling - QueueLine(cancelGCode); + QueueLine(this.CancelGCode); } // let the process know we canceled not ended normally. this.PrintWasCanceled = true; @@ -2149,7 +2109,7 @@ namespace MatterHackers.MatterControl.PrinterCommunication { gCodeFileStream0 = new GCodeFileStream(GCodeFile.Load(gcodeFilename, CancellationToken.None)); - if (printer.Settings.GetValue(SettingsKey.recover_is_enabled) + if (this.RecoveryIsEnabled && activePrintTask != null) // We are resuming a failed print (do lots of interesting stuff). { pauseHandlingStream1 = new PauseHandlingStream(printer, new PrintRecoveryStream(printer, gCodeFileStream0, activePrintTask.PercentDone)); @@ -2202,7 +2162,7 @@ namespace MatterHackers.MatterControl.PrinterCommunication private void LoadGCodeToPrint(string gcodeFilename) { - CreateStreamProcessors(gcodeFilename, printer.Settings.GetValue(SettingsKey.recover_is_enabled)); + CreateStreamProcessors(gcodeFilename, this.RecoveryIsEnabled); } private void DoneLoadingGCodeToPrint() @@ -2308,7 +2268,7 @@ namespace MatterHackers.MatterControl.PrinterCommunication private bool IsNetworkPrinting() { - return printer.Settings.GetValue(SettingsKey.enable_network_printing); + return this.EnableNetworkPrinting; } private void OnAtxPowerStateChanged(bool enableAtxPower) @@ -2485,7 +2445,7 @@ namespace MatterHackers.MatterControl.PrinterCommunication private void TurnOffBedAndExtruders() { - for (int i = 0; i < printer.Settings.GetValue(SettingsKey.extruder_count); i++) + for (int i = 0; i < this.ExtruderCount; i++) { SetTargetHotendTemperature(i, 0, true); } @@ -2501,7 +2461,7 @@ namespace MatterHackers.MatterControl.PrinterCommunication KeepTrackOfAbsolutePostionAndDestination(lineToWrite); - if (this.printer.Settings.GetValue(SettingsKey.send_with_checksum)) + if (this.SendWithChecksum) { // always send the reset line number without a checksum so that it is accepted string lineWithCount; From 59093ab73fae6d52e53ff28378e62ab1de6d0a16 Mon Sep 17 00:00:00 2001 From: John Lewin Date: Sat, 6 Jan 2018 16:03:03 -0800 Subject: [PATCH 2/2] Move ReadLine replacement string parsing back into PrinterConnection - Ensure update on settings change --- ApplicationView/PrinterModels.cs | 34 ++++------------------- PrinterCommunication/PrinterConnection.cs | 34 ++++++++++++++++++++--- 2 files changed, 36 insertions(+), 32 deletions(-) diff --git a/ApplicationView/PrinterModels.cs b/ApplicationView/PrinterModels.cs index f60966a56..4b8e49b93 100644 --- a/ApplicationView/PrinterModels.cs +++ b/ApplicationView/PrinterModels.cs @@ -618,10 +618,6 @@ namespace MatterHackers.MatterControl public class PrinterConfig { - private static Regex getQuotedParts = new Regex(@"([""'])(\\?.)*?\1", RegexOptions.Compiled); - private string constructedReadRegexString; - private string readRegexString = ""; - public BedConfig Bed { get; } private EventHandler unregisterEvents; @@ -664,32 +660,10 @@ namespace MatterHackers.MatterControl this.Connection.RecoveryIsEnabled = this.Settings.GetValue(SettingsKey.recover_is_enabled); this.Connection.ExtruderCount = this.Settings.GetValue(SettingsKey.extruder_count); this.Connection.SendWithChecksum = this.Settings.GetValue(SettingsKey.send_with_checksum); - - this.ConstructReadReplacements(); + this.Connection.ReadLineReplacementString = this.Settings.GetValue(SettingsKey.read_regex); } - private void ConstructReadReplacements() - { - string readRegex = this.Settings.GetValue(SettingsKey.read_regex); - - if (this.constructedReadRegexString != readRegex) - { - this.constructedReadRegexString = readRegex; - - this.Connection.ReadLineReplacements.Clear(); - - foreach (string regExLine in readRegex.Split(new string[] { "\\n" }, StringSplitOptions.RemoveEmptyEntries)) - { - var matches = getQuotedParts.Matches(regExLine); - if (matches.Count == 2) - { - var search = matches[0].Value.Substring(1, matches[0].Value.Length - 2); - var replace = matches[1].Value.Substring(1, matches[1].Value.Length - 2); - this.Connection.ReadLineReplacements.Add((new Regex(search, RegexOptions.Compiled), replace)); - } - } - } - } + public PrinterViewState ViewState { get; } = new PrinterViewState(); @@ -850,6 +824,10 @@ namespace MatterHackers.MatterControl case SettingsKey.send_with_checksum: this.Connection.SendWithChecksum = this.Settings.GetValue(SettingsKey.send_with_checksum); break; + + case SettingsKey.read_regex: + this.Connection.ReadLineReplacementString = this.Settings.GetValue(SettingsKey.read_regex); + break; } } } diff --git a/PrinterCommunication/PrinterConnection.cs b/PrinterCommunication/PrinterConnection.cs index 7d7edce38..5bd759a05 100644 --- a/PrinterCommunication/PrinterConnection.cs +++ b/PrinterCommunication/PrinterConnection.cs @@ -369,7 +369,34 @@ namespace MatterHackers.MatterControl.PrinterCommunication public bool RecoveryIsEnabled { get; set; } - public List<(Regex Regex, string Replacement)> ReadLineReplacements { get; set; } = new List<(Regex Regex, string Replacement)>(); + private List<(Regex Regex, string Replacement)> readLineReplacements = new List<(Regex Regex, string Replacement)>(); + + private string _readLineReplacementString = ""; + public string ReadLineReplacementString + { + get => _readLineReplacementString; + set + { + if (value != _readLineReplacementString) + { + _readLineReplacementString = value; + + // Clear and rebuild the replacement list + readLineReplacements.Clear(); + + foreach (string regExLine in _readLineReplacementString.Split(new string[] { "\\n" }, StringSplitOptions.RemoveEmptyEntries)) + { + var matches = getQuotedParts.Matches(regExLine); + if (matches.Count == 2) + { + var search = matches[0].Value.Substring(1, matches[0].Value.Length - 2); + var replace = matches[1].Value.Substring(1, matches[1].Value.Length - 2); + readLineReplacements.Add((new Regex(search, RegexOptions.Compiled), replace)); + } + } + } + } + } // PrinterSettings/Options }} @@ -790,7 +817,6 @@ namespace MatterHackers.MatterControl.PrinterCommunication // HACK: PrinterConnection must be revised to take a constructor that receives and stores a reference to its parent PrinterConfig - this private PrinterConfig printer { get; set; } - public string ReadRegex { get; private set; } public void ReleaseAndReportFailedConnection(ConnectionFailure reason, string details = null) { @@ -1806,13 +1832,13 @@ namespace MatterHackers.MatterControl.PrinterCommunication } #region ProcessRead - + private static Regex getQuotedParts = new Regex(@"([""'])(\\?.)*?\1", RegexOptions.Compiled); private List addedReadLines = new List(); private string ProcessReadRegEx(string lineBeingRead) { var addedLines = new List(); - foreach (var item in this.ReadLineReplacements) + foreach (var item in readLineReplacements) { var splitReplacement = item.Replacement.Split(','); if (splitReplacement.Length > 0)