mirror of
https://github.com/riegera2412/UVtools.git
synced 2026-07-08 17:42:31 +02:00
v2.6.0
* (Add) File format: Zcode (Uniz IBEE) * (Add) PrusaSlicer Printer: Uniz IBEE * (Add) Extract: Output an "Layer.ini" file containing per layer data and include the Configuration.ini for Zip file formats * (Improvement) Zip: Increase the GCode parsing performance * (Fix) File formats: Wasn't set bottom / light off delay per individual layer on generic formats, defaulting every layer to 0 * (Fix) Edit print paramenters: When changing bottom layer count, layers didnt update thier properties
This commit is contained in:
@@ -1,5 +1,14 @@
|
||||
# Changelog
|
||||
|
||||
## 25/02/2021 - v2.6.0
|
||||
|
||||
* (Add) File format: Zcode (Uniz IBEE)
|
||||
* (Add) PrusaSlicer Printer: Uniz IBEE
|
||||
* (Add) Extract: Output an "Layer.ini" file containing per layer data and include the Configuration.ini for Zip file formats
|
||||
* (Improvement) Zip: Increase the GCode parsing performance
|
||||
* (Fix) File formats: Wasn't set bottom / light off delay per individual layer on generic formats, defaulting every layer to 0
|
||||
* (Fix) Edit print paramenters: When changing bottom layer count, layers didnt update thier properties
|
||||
|
||||
## 25/02/2021 - v2.5.1
|
||||
|
||||
* (Add) Calibration - Exposure time finder: Option to "Do not perform the lifting sequence for layers with same Z positioning"
|
||||
|
||||
@@ -31,7 +31,7 @@ class FixedEncoder : System.Text.UTF8Encoding {
|
||||
####################################
|
||||
$enableMSI = $true
|
||||
$buildOnly = $null
|
||||
#$buildOnly = "osx-x64"#"win-x64"
|
||||
#$buildOnly = "win-x64"
|
||||
# Profilling
|
||||
$stopWatch = New-Object -TypeName System.Diagnostics.Stopwatch
|
||||
$deployStopWatch = New-Object -TypeName System.Diagnostics.Stopwatch
|
||||
@@ -103,6 +103,11 @@ $runtimes =
|
||||
"exclude" = @()
|
||||
"include" = @("libcvextern.so")
|
||||
}
|
||||
"linux-arm64" = @{
|
||||
"extraCmd" = "-p:PublishReadyToRun=true"
|
||||
"exclude" = @()
|
||||
"include" = @("libcvextern.so")
|
||||
}
|
||||
#"unix-x64" = @{
|
||||
# "extraCmd" = "-p:PublishReadyToRun=true"
|
||||
# "exclude" = @("x86", "x64", "libcvextern.dylib")
|
||||
|
||||
@@ -63,6 +63,7 @@ SET files[53]=Voxelab Ceres 8.9.ini
|
||||
SET files[54]=Longer Orange 10.ini
|
||||
SET files[55]=Longer Orange 30.ini
|
||||
SET files[56]=Longer Orange4K.ini
|
||||
SET files[57]=Uniz IBEE.ini
|
||||
|
||||
echo PrusaSlicer Printers Instalation
|
||||
echo This will replace printers, all changes will be discarded
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
# generated by PrusaSlicer 2.3.0+win64 on 2021-03-02 at 01:39:35 UTC
|
||||
absolute_correction = 0
|
||||
area_fill = 50
|
||||
bed_custom_model =
|
||||
bed_custom_texture =
|
||||
bed_shape = 0x0,192x0,192x120,0x120
|
||||
default_sla_material_profile = Prusa Orange Tough 0.05
|
||||
default_sla_print_profile = 0.05 Normal
|
||||
display_height = 120
|
||||
display_mirror_x = 0
|
||||
display_mirror_y = 1
|
||||
display_orientation = landscape
|
||||
display_pixels_x = 3840
|
||||
display_pixels_y = 2400
|
||||
display_width = 192
|
||||
elefant_foot_compensation = 0.2
|
||||
elefant_foot_min_width = 0.2
|
||||
fast_tilt_time = 5
|
||||
gamma_correction = 1
|
||||
host_type = octoprint
|
||||
inherits = Original Prusa SL1
|
||||
max_exposure_time = 120
|
||||
max_initial_exposure_time = 300
|
||||
max_print_height = 220
|
||||
min_exposure_time = 1
|
||||
min_initial_exposure_time = 1
|
||||
print_host =
|
||||
printer_model = SL1
|
||||
printer_notes = Don't remove the following keywords! These keywords are used in the "compatible printer" condition of the print and filament profiles to link the particular print and filament profiles to this printer profile.\nPRINTER_VENDOR_PRUSA3D\nPRINTER_MODEL_SL1\nPRINTER_VENDOR_UNIZ\nPRINTER_MODEL_IBEE\nFILEFORMAT_ZCODE\n\nSTART_CUSTOM_VALUES\nLightOffDelay_2\nBottomLightOffDelay_4\nBottomLiftHeight_15\nLiftHeight_7\nBottomLiftSpeed_20\nLiftSpeed_80\nRetractSpeed_80\nEND_CUSTOM_VALUES
|
||||
printer_settings_id =
|
||||
printer_technology = SLA
|
||||
printer_variant = default
|
||||
printer_vendor =
|
||||
printhost_apikey =
|
||||
printhost_cafile =
|
||||
relative_correction = 1,1
|
||||
slow_tilt_time = 8
|
||||
thumbnails = 400x400,800x480
|
||||
@@ -66,6 +66,7 @@ But also, i need victims for test subject. Proceed at your own risk!
|
||||
* PWMO (Photon Workshop)
|
||||
* PWMS (Photon Workshop)
|
||||
* PWMX (Photon Workshop)
|
||||
* ZCode (UnizMaker)
|
||||
* ZCodex (Z-Suite)
|
||||
* CWS (NovaMaker)
|
||||
* RGB.CWS (Nova Bene4 Mono / Elfin2 Mono SE)
|
||||
@@ -86,7 +87,6 @@ But also, i need victims for test subject. Proceed at your own risk!
|
||||
* X133 4K Mono
|
||||
* X156 4K Color
|
||||
* X1K 2K Mono
|
||||
* **Zortrax Inkspire**
|
||||
* **Nova3D**
|
||||
* Elfin
|
||||
* Bene4 Mono
|
||||
@@ -140,6 +140,8 @@ But also, i need victims for test subject. Proceed at your own risk!
|
||||
* Orange 10
|
||||
* Orange 30
|
||||
* Orange4K
|
||||
* **Uniz IBEE**
|
||||
* **Zortrax Inkspire**
|
||||
|
||||
# Available profiles for PrusaSlicer
|
||||
|
||||
|
||||
@@ -1,4 +1,11 @@
|
||||
using System;
|
||||
/*
|
||||
* GNU AFFERO GENERAL PUBLIC LICENSE
|
||||
* Version 3, 19 November 2007
|
||||
* Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
|
||||
* Everyone is permitted to copy and distribute verbatim copies
|
||||
* of this license document, but changing it is not allowed.
|
||||
*/
|
||||
using System;
|
||||
using System.Drawing;
|
||||
|
||||
namespace UVtools.Core.Extensions
|
||||
|
||||
@@ -1,4 +1,11 @@
|
||||
using System;
|
||||
/*
|
||||
* GNU AFFERO GENERAL PUBLIC LICENSE
|
||||
* Version 3, 19 November 2007
|
||||
* Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
|
||||
* Everyone is permitted to copy and distribute verbatim copies
|
||||
* of this license document, but changing it is not allowed.
|
||||
*/
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Text;
|
||||
|
||||
@@ -533,12 +533,6 @@ namespace UVtools.Core.FileFormats
|
||||
|
||||
#region Methods
|
||||
|
||||
public override void Clear()
|
||||
{
|
||||
base.Clear();
|
||||
GCode = null;
|
||||
}
|
||||
|
||||
protected override void EncodeInternally(string fileFullPath, OperationProgress progress)
|
||||
{
|
||||
//var filename = fileFullPath.EndsWith(TemporaryFileAppend) ? Path.GetFileNameWithoutExtension(Path.GetFileNameWithoutExtension(fileFullPath)) : Path.GetFileNameWithoutExtension(fileFullPath);
|
||||
|
||||
@@ -531,8 +531,8 @@ namespace UVtools.Core.FileFormats
|
||||
|
||||
|
||||
var startStr = $";LAYER_START:{layerIndex}";
|
||||
var stripGcode = gcode.Substring(gcode.IndexOf(startStr, StringComparison.InvariantCultureIgnoreCase) + startStr.Length);
|
||||
stripGcode = stripGcode.Substring(0, stripGcode.IndexOf(";LAYER_END")).Trim(' ', '\n', '\r', '\t');
|
||||
gcode = gcode.Substring(gcode.IndexOf(startStr, StringComparison.InvariantCultureIgnoreCase) + startStr.Length);
|
||||
var stripGcode = gcode.Substring(0, gcode.IndexOf(";LAYER_END")).Trim(' ', '\n', '\r', '\t');
|
||||
//var startCurrPos = stripGcode.Remove(0, ";currPos:".Length);
|
||||
|
||||
float posZ = lastPostZ;
|
||||
|
||||
@@ -10,7 +10,6 @@ using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Diagnostics;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
@@ -37,6 +36,8 @@ namespace UVtools.Core.FileFormats
|
||||
private const string ExtractConfigFileName = "Configuration";
|
||||
private const string ExtractConfigFileExtension = "ini";
|
||||
|
||||
|
||||
public const float DefaultLayerHeight = 0.5f;
|
||||
public const ushort DefaultBottomLayerCount = 4;
|
||||
|
||||
public const float DefaultBottomExposureTime = 30;
|
||||
@@ -206,8 +207,9 @@ namespace UVtools.Core.FileFormats
|
||||
new PHZFile(), // phz
|
||||
new FDGFile(), // fdg
|
||||
new PhotonWorkshopFile(), // PSW
|
||||
new ZCodexFile(), // zcodex
|
||||
new CWSFile(), // CWS
|
||||
new ZCodeFile(), // zcode
|
||||
new ZCodexFile(), // zcodex
|
||||
//new MakerbaseFile(), // MKS
|
||||
new LGSFile(), // LGS, LGS30
|
||||
new UVJFile(), // UVJ
|
||||
@@ -546,7 +548,7 @@ namespace UVtools.Core.FileFormats
|
||||
/// <summary>
|
||||
/// Gets or sets if images need to be mirrored on lcd to print on the correct orientation
|
||||
/// </summary>
|
||||
public abstract bool MirrorDisplay { get; set; }
|
||||
public virtual bool MirrorDisplay { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the maximum printer build Z volume
|
||||
@@ -1272,22 +1274,10 @@ namespace UVtools.Core.FileFormats
|
||||
//{
|
||||
Directory.CreateDirectory(path);
|
||||
//}
|
||||
|
||||
|
||||
if (FileType == FileFormatType.Archive)
|
||||
{
|
||||
|
||||
progress.CanCancel = false;
|
||||
//ZipFile.ExtractToDirectory(FileFullPath, path);
|
||||
ZipArchiveExtensions.ImprovedExtractToDirectory(FileFullPath, path, ZipArchiveExtensions.Overwrite.Always);
|
||||
return;
|
||||
}
|
||||
|
||||
progress.ItemCount = LayerCount;
|
||||
|
||||
if (genericConfigExtract)
|
||||
{
|
||||
if (!ReferenceEquals(Configs, null))
|
||||
if (Configs is not null)
|
||||
{
|
||||
using TextWriter tw = new StreamWriter(Path.Combine(path, $"{ExtractConfigFileName}.{ExtractConfigFileExtension}"), false);
|
||||
foreach (var config in Configs)
|
||||
@@ -1307,14 +1297,66 @@ namespace UVtools.Core.FileFormats
|
||||
}
|
||||
}
|
||||
|
||||
if (genericLayersExtract)
|
||||
{
|
||||
if (LayerCount > 0)
|
||||
{
|
||||
using (TextWriter tw = new StreamWriter(Path.Combine(path, "Layers.ini")))
|
||||
{
|
||||
for (int layerIndex = 0; layerIndex < LayerCount; layerIndex++)
|
||||
{
|
||||
var layer = this[layerIndex];
|
||||
tw.WriteLine($"[{layerIndex}]");
|
||||
tw.WriteLine($"{nameof(layer.NonZeroPixelCount)}: {layer.NonZeroPixelCount}");
|
||||
tw.WriteLine($"{nameof(layer.BoundingRectangle)}: {layer.BoundingRectangle}");
|
||||
tw.WriteLine($"{nameof(layer.IsBottomLayer)}: {layer.IsBottomLayer}");
|
||||
tw.WriteLine($"{nameof(layer.LayerHeight)}: {layer.LayerHeight}");
|
||||
tw.WriteLine($"{nameof(layer.PositionZ)}: {layer.PositionZ}");
|
||||
tw.WriteLine($"{nameof(layer.ExposureTime)}: {layer.ExposureTime}");
|
||||
|
||||
if (HavePrintParameterPerLayerModifier(PrintParameterModifier.LightOffDelay))
|
||||
tw.WriteLine($"{nameof(layer.LightOffDelay)}: {layer.LightOffDelay}");
|
||||
if (HavePrintParameterPerLayerModifier(PrintParameterModifier.LiftHeight))
|
||||
tw.WriteLine($"{nameof(layer.LiftHeight)}: {layer.LiftHeight}");
|
||||
if (HavePrintParameterPerLayerModifier(PrintParameterModifier.LiftSpeed))
|
||||
tw.WriteLine($"{nameof(layer.LiftSpeed)}: {layer.LiftSpeed}");
|
||||
if (HavePrintParameterPerLayerModifier(PrintParameterModifier.RetractSpeed))
|
||||
tw.WriteLine($"{nameof(layer.RetractSpeed)}: {layer.RetractSpeed}");
|
||||
if (HavePrintParameterPerLayerModifier(PrintParameterModifier.LightPWM))
|
||||
tw.WriteLine($"{nameof(layer.LightPWM)}: {layer.LightPWM}");
|
||||
|
||||
var materialMillilitersPercent = layer.MaterialMillilitersPercent;
|
||||
if (!float.IsNaN(materialMillilitersPercent))
|
||||
{
|
||||
tw.WriteLine($"{nameof(layer.MaterialMilliliters)}: {layer.MaterialMilliliters}ml ({materialMillilitersPercent:F2}%)");
|
||||
}
|
||||
|
||||
tw.WriteLine();
|
||||
}
|
||||
tw.Close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (FileType == FileFormatType.Archive)
|
||||
{
|
||||
|
||||
progress.CanCancel = false;
|
||||
ZipArchiveExtensions.ImprovedExtractToDirectory(FileFullPath, path, ZipArchiveExtensions.Overwrite.Always);
|
||||
return;
|
||||
}
|
||||
|
||||
progress.ItemCount = LayerCount;
|
||||
|
||||
if (genericLayersExtract)
|
||||
{
|
||||
uint i = 0;
|
||||
if (!ReferenceEquals(Thumbnails, null))
|
||||
if (Thumbnails is not null)
|
||||
{
|
||||
foreach (var thumbnail in Thumbnails)
|
||||
{
|
||||
if (ReferenceEquals(thumbnail, null))
|
||||
if (thumbnail is null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
@@ -1342,24 +1384,6 @@ namespace UVtools.Core.FileFormats
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/* Parallel.For(0, LayerCount, layerIndex => {
|
||||
var byteArr = this[layerIndex].RawData;
|
||||
using (FileStream stream = File.Create(Path.Combine(path, $"Layer{layerIndex}.png"), byteArr.Length))
|
||||
{
|
||||
stream.Write(byteArr, 0, byteArr.Length);
|
||||
stream.Close();
|
||||
}
|
||||
});*/
|
||||
/*for (i = 0; i < LayerCount; i++)
|
||||
{
|
||||
var byteArr = GetLayer(i);
|
||||
using (FileStream stream = File.Create(Path.Combine(path, $"Layer{i}.png"), byteArr.Length))
|
||||
{
|
||||
stream.Write(byteArr, 0, byteArr.Length);
|
||||
stream.Close();
|
||||
}
|
||||
}*/
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,795 @@
|
||||
/*
|
||||
* GNU AFFERO GENERAL PUBLIC LICENSE
|
||||
* Version 3, 19 November 2007
|
||||
* Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
|
||||
* Everyone is permitted to copy and distribute verbatim copies
|
||||
* of this license document, but changing it is not allowed.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.IO.Compression;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Xml.Serialization;
|
||||
using Emgu.CV;
|
||||
using Emgu.CV.CvEnum;
|
||||
using Emgu.CV.Util;
|
||||
using Org.BouncyCastle.Crypto;
|
||||
using Org.BouncyCastle.Crypto.Engines;
|
||||
using Org.BouncyCastle.OpenSsl;
|
||||
using UVtools.Core.Extensions;
|
||||
using UVtools.Core.Operations;
|
||||
|
||||
namespace UVtools.Core.FileFormats
|
||||
{
|
||||
[Serializable]
|
||||
[XmlRoot(ElementName = "Print")]
|
||||
public class ZCodePrint
|
||||
{
|
||||
[Serializable]
|
||||
[XmlRoot(ElementName = "Device")]
|
||||
public class ZcodePrintDevice
|
||||
{
|
||||
[XmlAttribute("z")]
|
||||
public ushort MachineZ { get; set; } = 220;
|
||||
|
||||
[XmlAttribute("height")]
|
||||
public uint ResolutionY { get; set; } = 2400;
|
||||
|
||||
[XmlAttribute("width")]
|
||||
public uint ResolutionX { get; set; } = 3840;
|
||||
|
||||
[XmlAttribute("type")]
|
||||
public string MachineModel { get; set; } = "IBEE";
|
||||
|
||||
[XmlAttribute("pixel_size")]
|
||||
public float PixelSize { get; set; } = 50;
|
||||
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
[XmlRoot(ElementName = "Profile")]
|
||||
public class ZcodePrintProfile
|
||||
{
|
||||
[XmlAttribute("name")]
|
||||
public string Name { get; set; } = "UVtools";
|
||||
|
||||
[Serializable]
|
||||
[XmlRoot(ElementName = "Slice")]
|
||||
public class ZcodePrintProfileSlice
|
||||
{
|
||||
[XmlAttribute("bottom_layers")]
|
||||
public ushort BottomLayerCount { get; set; } = FileFormat.DefaultBottomLayerCount;
|
||||
|
||||
[XmlAttribute("exposure_bottom")]
|
||||
public uint BottomExposureTime { get; set; } = (uint) (FileFormat.DefaultBottomExposureTime * 1000);
|
||||
|
||||
[XmlAttribute("exposure")]
|
||||
public uint ExposureTime { get; set; } = (uint) (FileFormat.DefaultExposureTime * 1000);
|
||||
|
||||
[XmlAttribute("height_bottom")]
|
||||
public float BottomLiftHeight { get; set; } = FileFormat.DefaultBottomLiftHeight;
|
||||
|
||||
[XmlAttribute("speed_bottom")]
|
||||
public float BottomLiftSpeed { get; set; } = FileFormat.DefaultBottomLiftSpeed;
|
||||
|
||||
[XmlAttribute("height")]
|
||||
public float LiftHeight { get; set; } = FileFormat.DefaultLiftHeight;
|
||||
|
||||
[XmlAttribute("speed")]
|
||||
public float LiftSpeed { get; set; } = FileFormat.DefaultLiftSpeed;
|
||||
|
||||
[XmlAttribute("cooldown_bottom")]
|
||||
public uint BottomLightOffDelay { get; set; } = (uint) (FileFormat.DefaultBottomLightOffDelay * 1000);
|
||||
|
||||
[XmlAttribute("cooldown")]
|
||||
public uint LightOffDelay { get; set; } = (uint) (FileFormat.DefaultLightOffDelay * 1000);
|
||||
|
||||
[XmlAttribute("thickness")]
|
||||
public float LayerHeight { get; set; } = FileFormat.DefaultLayerHeight;
|
||||
|
||||
[XmlAttribute("anti_aliasing_level")]
|
||||
public byte AntiAliasing { get; set; }
|
||||
|
||||
[XmlAttribute("anti_aliasing_grey_level")]
|
||||
public byte AntiAliasingGrey { get; set; }
|
||||
|
||||
[XmlAttribute("led_power")]
|
||||
public ushort LedPower { get; set; } = 300;
|
||||
}
|
||||
|
||||
public ZcodePrintProfileSlice Slice { get; set; } = new();
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
[XmlRoot(ElementName = "Job")]
|
||||
public class ZcodePrintJob
|
||||
{
|
||||
[XmlElement("name")]
|
||||
public string StlName { get; set; }
|
||||
|
||||
[XmlElement("previewImage")]
|
||||
public string PreviewImage { get; set; } = ZCodeFile.PreviewFilename;
|
||||
|
||||
[XmlElement("layers")]
|
||||
public uint LayerCount { get; set; }
|
||||
|
||||
[XmlElement("time")]
|
||||
public uint PrintTime { get; set; }
|
||||
|
||||
[XmlElement("volumn")]
|
||||
public float VolumeMl { get; set; }
|
||||
|
||||
[XmlElement("thickness")]
|
||||
public float LayerHeight { get; set; }
|
||||
|
||||
[XmlElement("price")]
|
||||
public float Price { get; set; }
|
||||
|
||||
[XmlElement("weight")]
|
||||
public float WeightG { get; set; }
|
||||
}
|
||||
|
||||
public ZcodePrintDevice Device = new();
|
||||
|
||||
public ZcodePrintProfile Profile = new();
|
||||
|
||||
public ZcodePrintJob Job = new();
|
||||
|
||||
}
|
||||
public class ZCodeFile : FileFormat
|
||||
{
|
||||
#region Constants
|
||||
|
||||
public const string GCodeFilename = "lcd.gcode";
|
||||
public const string ManifestFilename = "task.xml";
|
||||
public const string PreviewFilename = "preview.png";
|
||||
|
||||
public const string GCodeStart = "G21;{0}" + // Set units to be mm
|
||||
"G90;{0}" + // Absolute Positioning
|
||||
"M106 S0;{0}" + // Light Off
|
||||
"G28 Z0;{0}"; // Home
|
||||
|
||||
public const string GCodeEnd = "M106 S0{0}" + // Light Off
|
||||
"G1 Z{1} F10;{0}" + // Raize Z
|
||||
"M18;{0}"; // Disable Motors
|
||||
|
||||
public const string GCodeRSAPrivateKey =
|
||||
"-----BEGIN PRIVATE KEY-----\n" +
|
||||
"MIIBVQIBADANBgkqhkiG9w0BAQEFAASCAT8wggE7AgEAAkEA6BnF3oT9Ap+OyZFs" +
|
||||
"p02ZRtTpbMUA96PpctTXev1cPCclLuowXWNa3f2JBpPbPrzMwLam3JSQN3HjvYfS" +
|
||||
"Vx7e6wIDAQABAkBibCNzQ/PCfAThxxBLNeXMmpbNsBDD8rcZIdaqaewF+UjUlqI7" +
|
||||
"eI0Yp2V2Ez28FjKCEiM34DxU9PZTzYS3rCShAiEA9qp9+RwYvcvQUXlT2bqKIo3s" +
|
||||
"xu7LQFM4VIddQ1SMVhsCIQDw4i74LqF285Iz77vw1MXE06LHKKBBBa3Air1QNBhn" +
|
||||
"cQIgYfO4TLk8lfoewovkoVyzSB+F/EWNjwC9KMwMXBVyGSsCIQDisxudOtV+y3C3" +
|
||||
"LFHmL3kI6lxxrsxTJXMGmAvfJYgqIQIhAKBtzYeZB46EToDSpeYlrMQitSWvjgNG" +
|
||||
"mw+8aB/HYEIr\n" +
|
||||
"-----END PRIVATE KEY-----";
|
||||
|
||||
public const string GCodeRSAPublicKey =
|
||||
"-----BEGIN PUBLIC KEY-----\n" +
|
||||
"MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAOgZxd6E/QKfjsmRbKdNmUbU6WzFAPej" +
|
||||
"6XLU13r9XDwnJS7qMF1jWt39iQaT2z68zMC2ptyUkDdx472H0lce3usCAwEAAQ==\n" +
|
||||
"-----END PUBLIC KEY-----";
|
||||
|
||||
#endregion
|
||||
|
||||
#region Sub Classes
|
||||
|
||||
#endregion
|
||||
|
||||
#region Properties
|
||||
public ZCodePrint ManifestFile { get; set; } = new ();
|
||||
|
||||
public override FileFormatType FileType => FileFormatType.Archive;
|
||||
|
||||
public override FileExtension[] FileExtensions { get; } = {
|
||||
new("zcode", "UnizMaker ZCode files")
|
||||
};
|
||||
|
||||
public override PrintParameterModifier[] PrintParameterModifiers { get; } = {
|
||||
PrintParameterModifier.BottomLayerCount,
|
||||
PrintParameterModifier.BottomExposureSeconds,
|
||||
PrintParameterModifier.ExposureSeconds,
|
||||
|
||||
PrintParameterModifier.BottomLightOffDelay,
|
||||
PrintParameterModifier.LightOffDelay,
|
||||
PrintParameterModifier.BottomLiftHeight,
|
||||
PrintParameterModifier.BottomLiftSpeed,
|
||||
PrintParameterModifier.LiftHeight,
|
||||
PrintParameterModifier.LiftSpeed,
|
||||
PrintParameterModifier.RetractSpeed,
|
||||
|
||||
//PrintParameterModifier.BottomLightPWM,
|
||||
//PrintParameterModifier.LightPWM,
|
||||
};
|
||||
|
||||
public override PrintParameterModifier[] PrintParameterPerLayerModifiers { get; } = {
|
||||
PrintParameterModifier.ExposureSeconds,
|
||||
PrintParameterModifier.LightOffDelay,
|
||||
PrintParameterModifier.LiftHeight,
|
||||
PrintParameterModifier.LiftSpeed,
|
||||
PrintParameterModifier.RetractSpeed,
|
||||
//PrintParameterModifier.LightPWM,
|
||||
};
|
||||
|
||||
public override byte ThumbnailsCount { get; } = 1;
|
||||
|
||||
public override Size[] ThumbnailsOriginalSize { get; } = {new(640, 480)};
|
||||
|
||||
public override uint ResolutionX
|
||||
{
|
||||
get => ManifestFile.Device.ResolutionX;
|
||||
set
|
||||
{
|
||||
ManifestFile.Device.ResolutionX = value;
|
||||
RaisePropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
public override uint ResolutionY
|
||||
{
|
||||
get => ManifestFile.Device.ResolutionY;
|
||||
set
|
||||
{
|
||||
ManifestFile.Device.ResolutionY = value;
|
||||
RaisePropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
public override float DisplayWidth
|
||||
{
|
||||
get => (float) Math.Round(ManifestFile.Device.ResolutionX * ManifestFile.Device.PixelSize / 1000, 2);
|
||||
set => RaisePropertyChanged();
|
||||
}
|
||||
|
||||
public override float DisplayHeight
|
||||
{
|
||||
get => (float)Math.Round(ManifestFile.Device.ResolutionY * ManifestFile.Device.PixelSize / 1000, 2);
|
||||
set => RaisePropertyChanged();
|
||||
}
|
||||
|
||||
public override float MaxPrintHeight
|
||||
{
|
||||
get => ManifestFile.Device.MachineZ > 0 ? ManifestFile.Device.MachineZ : base.MaxPrintHeight;
|
||||
set
|
||||
{
|
||||
ManifestFile.Device.MachineZ = (ushort) value;
|
||||
RaisePropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
public override bool MirrorDisplay => true;
|
||||
|
||||
public override byte AntiAliasing
|
||||
{
|
||||
get => ManifestFile.Profile.Slice.AntiAliasing;
|
||||
set
|
||||
{
|
||||
ManifestFile.Profile.Slice.AntiAliasing = value.Clamp(1, 16);
|
||||
RaisePropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
public override float LayerHeight
|
||||
{
|
||||
get => ManifestFile.Job.LayerHeight;
|
||||
set
|
||||
{
|
||||
ManifestFile.Job.LayerHeight = ManifestFile.Profile.Slice.LayerHeight = (float)Math.Round(value, 2);
|
||||
RaisePropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
public override uint LayerCount
|
||||
{
|
||||
set
|
||||
{
|
||||
ManifestFile.Job.LayerCount = LayerCount;
|
||||
RaisePropertyChanged();
|
||||
RaisePropertyChanged(nameof(NormalLayerCount));
|
||||
}
|
||||
}
|
||||
|
||||
public override ushort BottomLayerCount
|
||||
{
|
||||
get => ManifestFile.Profile.Slice.BottomLayerCount;
|
||||
set
|
||||
{
|
||||
ManifestFile.Profile.Slice.BottomLayerCount = value;
|
||||
RaisePropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
public override float BottomExposureTime
|
||||
{
|
||||
get => (float)Math.Round(ManifestFile.Profile.Slice.BottomExposureTime / 1000f, 2);
|
||||
set
|
||||
{
|
||||
ManifestFile.Profile.Slice.BottomExposureTime = (uint) (value * 1000);
|
||||
RaisePropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
public override float ExposureTime
|
||||
{
|
||||
get => (float)Math.Round(ManifestFile.Profile.Slice.ExposureTime / 1000f, 2);
|
||||
set
|
||||
{
|
||||
ManifestFile.Profile.Slice.ExposureTime = (uint)(value * 1000);
|
||||
RaisePropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
public override float BottomLightOffDelay
|
||||
{
|
||||
get => (float)Math.Round(ManifestFile.Profile.Slice.BottomLightOffDelay / 1000f, 2);
|
||||
set
|
||||
{
|
||||
ManifestFile.Profile.Slice.BottomLightOffDelay = (uint)(value * 1000);
|
||||
RaisePropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
public override float LightOffDelay
|
||||
{
|
||||
get => (float)Math.Round(ManifestFile.Profile.Slice.LightOffDelay / 1000f, 2);
|
||||
set
|
||||
{
|
||||
ManifestFile.Profile.Slice.LightOffDelay = (uint)(value * 1000);
|
||||
RaisePropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
public override float BottomLiftHeight
|
||||
{
|
||||
get => ManifestFile.Profile.Slice.BottomLiftHeight;
|
||||
set
|
||||
{
|
||||
ManifestFile.Profile.Slice.BottomLiftHeight = (float)Math.Round(value, 2);
|
||||
RaisePropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
public override float LiftHeight
|
||||
{
|
||||
get => ManifestFile.Profile.Slice.LiftHeight;
|
||||
set
|
||||
{
|
||||
ManifestFile.Profile.Slice.LiftHeight = (float)Math.Round(value, 2);
|
||||
RaisePropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
public override float BottomLiftSpeed
|
||||
{
|
||||
get => ManifestFile.Profile.Slice.BottomLiftSpeed;
|
||||
set
|
||||
{
|
||||
ManifestFile.Profile.Slice.BottomLiftSpeed = (float)Math.Round(value, 2);
|
||||
RaisePropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
public override float LiftSpeed
|
||||
{
|
||||
get => ManifestFile.Profile.Slice.LiftSpeed;
|
||||
set
|
||||
{
|
||||
ManifestFile.Profile.Slice.LiftSpeed = (float)Math.Round(value, 2);
|
||||
RaisePropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
/*public override float RetractSpeed
|
||||
{
|
||||
get => HeaderSettings.RetractSpeed;
|
||||
set
|
||||
{
|
||||
HeaderSettings.RetractSpeed = (float)Math.Round(value, 2);
|
||||
RaisePropertyChanged();
|
||||
}
|
||||
}*/
|
||||
|
||||
public override float PrintTime
|
||||
{
|
||||
get => base.PrintTime;
|
||||
set
|
||||
{
|
||||
base.PrintTime = value;
|
||||
ManifestFile.Job.PrintTime = (uint) base.PrintTime;
|
||||
}
|
||||
}
|
||||
|
||||
public override float MaterialMilliliters
|
||||
{
|
||||
get => base.MaterialMilliliters;
|
||||
set
|
||||
{
|
||||
base.MaterialMilliliters = value;
|
||||
ManifestFile.Job.VolumeMl = base.MaterialMilliliters;
|
||||
}
|
||||
}
|
||||
|
||||
public override float MaterialGrams
|
||||
{
|
||||
get => ManifestFile.Job.WeightG;
|
||||
set
|
||||
{
|
||||
ManifestFile.Job.WeightG = (float)Math.Round(value, 3);
|
||||
RaisePropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
public override float MaterialCost
|
||||
{
|
||||
get => ManifestFile.Job.Price;
|
||||
set
|
||||
{
|
||||
ManifestFile.Job.Price = (float)Math.Round(value, 3);
|
||||
RaisePropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
/*public override string MaterialName
|
||||
{
|
||||
get => HeaderSettings.Resin;
|
||||
set
|
||||
{
|
||||
HeaderSettings.Resin = value;
|
||||
RaisePropertyChanged();
|
||||
}
|
||||
}*/
|
||||
|
||||
public override string MachineName
|
||||
{
|
||||
get => ManifestFile.Device.MachineModel;
|
||||
set
|
||||
{
|
||||
ManifestFile.Device.MachineModel = value;
|
||||
RequireFullEncode = true;
|
||||
RaisePropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
public override object[] Configs => new object[] { ManifestFile.Device, ManifestFile.Job, ManifestFile.Profile.Slice };
|
||||
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
|
||||
protected override void EncodeInternally(string fileFullPath, OperationProgress progress)
|
||||
{
|
||||
using (ZipArchive outputFile = ZipFile.Open(fileFullPath, ZipArchiveMode.Create))
|
||||
{
|
||||
if (Thumbnails.Length > 0 && Thumbnails[0] is not null)
|
||||
{
|
||||
using var thumbnailsStream = outputFile.CreateEntry(PreviewFilename).Open();
|
||||
using var vec = new VectorOfByte();
|
||||
CvInvoke.Imencode(".png", Thumbnails[0], vec);
|
||||
thumbnailsStream.WriteBytes(vec.ToArray());
|
||||
thumbnailsStream.Close();
|
||||
}
|
||||
|
||||
for (uint layerIndex = 0; layerIndex < LayerCount; layerIndex++)
|
||||
{
|
||||
progress.Token.ThrowIfCancellationRequested();
|
||||
var layer = this[layerIndex];
|
||||
outputFile.PutFileContent($"{layerIndex + 1}.png", layer.CompressedBytes, ZipArchiveMode.Create);
|
||||
progress++;
|
||||
}
|
||||
|
||||
XmlSerializer serializer = new XmlSerializer(ManifestFile.GetType());
|
||||
XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
|
||||
ns.Add("", "");
|
||||
var entry = outputFile.CreateEntry(ManifestFilename);
|
||||
using (var stream = entry.Open())
|
||||
{
|
||||
serializer.Serialize(stream, ManifestFile, ns);
|
||||
}
|
||||
|
||||
outputFile.PutFileContent(GCodeFilename, EncryptGCode(progress), ZipArchiveMode.Create);
|
||||
}
|
||||
}
|
||||
|
||||
protected override void DecodeInternally(string fileFullPath, OperationProgress progress)
|
||||
{
|
||||
using (var inputFile = ZipFile.Open(FileFullPath, ZipArchiveMode.Read))
|
||||
{
|
||||
var entry = inputFile.GetEntry(ManifestFilename);
|
||||
if (entry is null)
|
||||
{
|
||||
Clear();
|
||||
throw new FileLoadException($"{ManifestFilename} not found", fileFullPath);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var serializer = new XmlSerializer(ManifestFile.GetType());
|
||||
using var stream = entry.Open();
|
||||
ManifestFile = (ZCodePrint)serializer.Deserialize(stream);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Clear();
|
||||
throw new FileLoadException($"Unable to deserialize '{entry.Name}'\n{e}", fileFullPath);
|
||||
}
|
||||
|
||||
entry = inputFile.GetEntry(GCodeFilename);
|
||||
if (entry is null)
|
||||
{
|
||||
Clear();
|
||||
throw new FileLoadException($"{GCodeFilename} not found", fileFullPath);
|
||||
}
|
||||
|
||||
GCode = new();
|
||||
|
||||
var encryptEngine = new RsaEngine();
|
||||
using var txtreader = new StringReader(GCodeRSAPublicKey);
|
||||
var keyParameter = (AsymmetricKeyParameter)new PemReader(txtreader).ReadObject();
|
||||
encryptEngine.Init(true, keyParameter);
|
||||
|
||||
|
||||
|
||||
using (TextReader tr = new StreamReader(entry.Open()))
|
||||
{
|
||||
string line;
|
||||
progress.Reset("Decrypting GCode", (uint) (entry.Length / 88));
|
||||
while ((line = tr.ReadLine()) != null)
|
||||
{
|
||||
if (string.IsNullOrEmpty(line)) continue;
|
||||
if (!line.EndsWith("=="))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
byte[] data = System.Convert.FromBase64String(line);
|
||||
var decodedBytes = encryptEngine.ProcessBlock(data, 0, data.Length);
|
||||
decodedBytes = decodedBytes.Skip(2).SkipWhile(b => b == 255 || b == 0).ToArray();
|
||||
GCode.AppendLine(Encoding.UTF8.GetString(decodedBytes));
|
||||
|
||||
progress++;
|
||||
}
|
||||
|
||||
tr.Close();
|
||||
}
|
||||
|
||||
LayerManager = new LayerManager(ManifestFile.Job.LayerCount, this);
|
||||
progress.Reset(OperationProgress.StatusDecodeLayers, LayerCount);
|
||||
|
||||
var gcode = GCode.ToString();
|
||||
float lastPostZ = LayerHeight;
|
||||
|
||||
for (uint layerIndex = 0; layerIndex < LayerCount; layerIndex++)
|
||||
{
|
||||
if (progress.Token.IsCancellationRequested) break;
|
||||
entry = inputFile.GetEntry($"{layerIndex+1}.png");
|
||||
if (entry is null)
|
||||
{
|
||||
Clear();
|
||||
throw new FileLoadException($"Layer {layerIndex+1} not found", fileFullPath);
|
||||
}
|
||||
|
||||
var startStr = $"M6054 \"{layerIndex+1}.png\"";
|
||||
gcode = gcode.Substring(gcode.IndexOf(startStr, StringComparison.InvariantCultureIgnoreCase) + startStr.Length + 1);
|
||||
var stripGcode = gcode.Substring(0, gcode.IndexOf("M106 S0")).Trim(' ', '\n', '\r', '\t');
|
||||
//var startCurrPos = stripGcode.Remove(0, ";currPos:".Length);
|
||||
|
||||
float posZ = lastPostZ;
|
||||
float liftHeight = GetInitialLayerValueOrNormal(layerIndex, BottomLiftHeight, LiftHeight);
|
||||
float liftSpeed = GetInitialLayerValueOrNormal(layerIndex, BottomLiftSpeed, LiftSpeed);
|
||||
float retractSpeed = RetractSpeed;
|
||||
float lightOffDelay = 0;
|
||||
byte pwm = GetInitialLayerValueOrNormal(layerIndex, BottomLightPWM, LightPWM); ;
|
||||
float exposureTime = GetInitialLayerValueOrNormal(layerIndex, BottomExposureTime, ExposureTime);
|
||||
|
||||
//var currPosRegex = Regex.Match(stripGcode, @";currPos:([+-]?([0-9]*[.])?[0-9]+)", RegexOptions.IgnoreCase);
|
||||
var moveG0Regex = Regex.Match(stripGcode, @"G0 Z([+-]?([0-9]*[.])?[0-9]+) F(\d+)", RegexOptions.IgnoreCase);
|
||||
var waitG4Regex = Regex.Match(stripGcode, @"G4 P(\d+)", RegexOptions.IgnoreCase);
|
||||
var pwmM106Regex = Regex.Match(stripGcode, @"M106 S(\d+)", RegexOptions.IgnoreCase);
|
||||
|
||||
if (moveG0Regex.Success)
|
||||
{
|
||||
float liftHeightTemp = float.Parse(moveG0Regex.Groups[1].Value, CultureInfo.InvariantCulture);
|
||||
float liftSpeedTemp = float.Parse(moveG0Regex.Groups[3].Value, CultureInfo.InvariantCulture);
|
||||
moveG0Regex = moveG0Regex.NextMatch();
|
||||
if (moveG0Regex.Success)
|
||||
{
|
||||
float retractHeight = float.Parse(moveG0Regex.Groups[1].Value, CultureInfo.InvariantCulture);
|
||||
retractSpeed = float.Parse(moveG0Regex.Groups[3].Value, CultureInfo.InvariantCulture) * 10;
|
||||
liftHeight = (float) Math.Round(liftHeightTemp - retractHeight, 2);
|
||||
liftSpeed = liftSpeedTemp * 10;
|
||||
lastPostZ = posZ = retractHeight;
|
||||
}
|
||||
else
|
||||
{
|
||||
lastPostZ = posZ = liftHeightTemp;
|
||||
}
|
||||
}
|
||||
|
||||
if (pwmM106Regex.Success)
|
||||
{
|
||||
//pwm = byte.Parse(pwmM106Regex.Groups[1].Value);
|
||||
}
|
||||
|
||||
if (waitG4Regex.Success)
|
||||
{
|
||||
lightOffDelay = (float) Math.Round(float.Parse(waitG4Regex.Groups[1].Value, CultureInfo.InvariantCulture) / 1000f, 2);
|
||||
waitG4Regex = waitG4Regex.NextMatch();
|
||||
if (waitG4Regex.Success)
|
||||
{
|
||||
exposureTime = (float) Math.Round(float.Parse(waitG4Regex.Groups[1].Value, CultureInfo.InvariantCulture) / 1000f, 2);
|
||||
}
|
||||
else // Only one match, meaning light off delay is not present
|
||||
{
|
||||
lightOffDelay = GetInitialLayerValueOrNormal(layerIndex, BottomLightOffDelay, LightOffDelay);
|
||||
}
|
||||
}
|
||||
|
||||
this[layerIndex] = new Layer(layerIndex, entry.Open(), LayerManager)
|
||||
{
|
||||
PositionZ = posZ,
|
||||
ExposureTime = exposureTime,
|
||||
LiftHeight = liftHeight,
|
||||
LiftSpeed = liftSpeed,
|
||||
RetractSpeed = retractSpeed,
|
||||
LightOffDelay = lightOffDelay,
|
||||
LightPWM = pwm,
|
||||
};
|
||||
progress++;
|
||||
}
|
||||
|
||||
|
||||
entry = inputFile.GetEntry(PreviewFilename);
|
||||
if (entry is not null)
|
||||
{
|
||||
Thumbnails[0] = new Mat();
|
||||
CvInvoke.Imdecode(entry.Open().ToArray(), ImreadModes.AnyColor, Thumbnails[0]);
|
||||
}
|
||||
}
|
||||
|
||||
LayerManager.GetBoundingRectangle(progress);
|
||||
}
|
||||
|
||||
public override void RebuildGCode()
|
||||
{
|
||||
GCode = new();
|
||||
|
||||
GCode.AppendFormat(GCodeStart, Environment.NewLine);
|
||||
|
||||
float lastZPosition = 0;
|
||||
|
||||
for (uint layerIndex = 0; layerIndex < LayerCount; layerIndex++)
|
||||
{
|
||||
var layer = this[layerIndex];
|
||||
var exposureTime = layer.ExposureTime * 1000;
|
||||
var liftHeight = layer.LiftHeight;
|
||||
var liftZHeight = Math.Round(liftHeight + layer.PositionZ, 2);
|
||||
var liftSpeed = Math.Round(layer.LiftSpeed / 10, 2);
|
||||
var retractSpeed = Math.Round(layer.RetractSpeed / 10, 2);
|
||||
var lightOffDelay = layer.LightOffDelay * 1000;
|
||||
var pwmValue = layer.LightPWM;
|
||||
|
||||
if (layer.ExposureTime > 0 && pwmValue > 0)
|
||||
{
|
||||
GCode.AppendLine($"M6054 \"{layerIndex + 1}.png\";");
|
||||
}
|
||||
|
||||
// Absolute gcode
|
||||
if (liftHeight > 0 && liftZHeight > layer.PositionZ)
|
||||
{
|
||||
GCode.AppendLine($"G0 Z{liftZHeight} F{liftSpeed};");
|
||||
GCode.AppendLine($"G0 Z{layer.PositionZ} F{retractSpeed};");
|
||||
}
|
||||
else if (lastZPosition < layer.PositionZ)
|
||||
{
|
||||
GCode.AppendLine($"G0 Z{layer.PositionZ} F{retractSpeed};");
|
||||
}
|
||||
|
||||
GCode.AppendLine($"G4 P{lightOffDelay};");
|
||||
|
||||
if (layer.ExposureTime > 0 && pwmValue > 0)
|
||||
{
|
||||
GCode.AppendLine($"M106 S300;");
|
||||
GCode.AppendLine($"G4 P{exposureTime};");
|
||||
GCode.AppendLine("M106 S0;");
|
||||
}
|
||||
|
||||
lastZPosition = layer.PositionZ;
|
||||
}
|
||||
|
||||
GCode.AppendFormat(GCodeEnd, Environment.NewLine, MaxPrintHeight);
|
||||
}
|
||||
|
||||
public override void SaveAs(string filePath = null, OperationProgress progress = null)
|
||||
{
|
||||
if (RequireFullEncode)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(filePath))
|
||||
{
|
||||
FileFullPath = filePath;
|
||||
}
|
||||
Encode(FileFullPath, progress);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(filePath))
|
||||
{
|
||||
File.Copy(FileFullPath, filePath, true);
|
||||
FileFullPath = filePath;
|
||||
}
|
||||
|
||||
using var outputFile = ZipFile.Open(FileFullPath, ZipArchiveMode.Update);
|
||||
bool deleted;
|
||||
|
||||
do
|
||||
{
|
||||
deleted = false;
|
||||
foreach (var zipentry in outputFile.Entries)
|
||||
{
|
||||
if (!zipentry.Name.EndsWith(".gcode") && !zipentry.Name.EndsWith(".xml")) continue;
|
||||
zipentry.Delete();
|
||||
deleted = true;
|
||||
break;
|
||||
}
|
||||
} while (deleted);
|
||||
|
||||
XmlSerializer serializer = new XmlSerializer(ManifestFile.GetType());
|
||||
XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
|
||||
ns.Add("", "");
|
||||
var entry = outputFile.CreateEntry(ManifestFilename);
|
||||
using var stream = entry.Open();
|
||||
serializer.Serialize(stream, ManifestFile, ns);
|
||||
|
||||
outputFile.PutFileContent(GCodeFilename, EncryptGCode(progress), ZipArchiveMode.Update);
|
||||
|
||||
//Decode(FileFullPath, progress);
|
||||
}
|
||||
|
||||
private string EncryptGCode(OperationProgress progress)
|
||||
{
|
||||
RebuildGCode();
|
||||
progress.Reset("Encrypting GCode", (uint) GCode.Length);
|
||||
StringBuilder sb = new();
|
||||
|
||||
var encryptEngine = new RsaEngine();
|
||||
using var txtreader = new StringReader(GCodeRSAPrivateKey);
|
||||
var keyParameter = (AsymmetricKeyParameter)new PemReader(txtreader).ReadObject();
|
||||
encryptEngine.Init(true, keyParameter);
|
||||
|
||||
using StringReader sr = new StringReader(GCode.ToString());
|
||||
string line;
|
||||
while ((line = sr.ReadLine()) != null)
|
||||
{
|
||||
progress += (uint)line.Length;
|
||||
|
||||
byte[] data = Encoding.UTF8.GetBytes(line);
|
||||
List<byte> padData = new(64) {0, 1, 0};
|
||||
padData.AddRange(data);
|
||||
|
||||
if (padData.Count > 64)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException($"Too long gcode line to encrypt, got: {padData.Count} bytes while expecting less than 64 bytes");
|
||||
}
|
||||
|
||||
while (padData.Count < 64)
|
||||
{
|
||||
padData.Insert(2, 255);
|
||||
}
|
||||
|
||||
var padDataArray = padData.ToArray();
|
||||
|
||||
var encodedBytes = encryptEngine.ProcessBlock(padDataArray, 0, padDataArray.Length);
|
||||
sb.AppendLine(System.Convert.ToBase64String(encodedBytes));
|
||||
}
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -370,6 +370,7 @@ namespace UVtools.Core
|
||||
_exposureTime = SlicerFile.GetInitialLayerValueOrNormal(index, SlicerFile.BottomExposureTime, SlicerFile.ExposureTime);
|
||||
_liftHeight = SlicerFile.GetInitialLayerValueOrNormal(index, SlicerFile.BottomLiftHeight, SlicerFile.LiftHeight);
|
||||
_liftSpeed = SlicerFile.GetInitialLayerValueOrNormal(index, SlicerFile.BottomLiftSpeed, SlicerFile.LiftSpeed);
|
||||
_lightOffDelay = SlicerFile.GetInitialLayerValueOrNormal(index, SlicerFile.BottomLightOffDelay, SlicerFile.LightOffDelay);
|
||||
_retractSpeed = SlicerFile.RetractSpeed;
|
||||
_lightPwm = SlicerFile.GetInitialLayerValueOrNormal(index, SlicerFile.BottomLightPWM, SlicerFile.LightPWM);
|
||||
}
|
||||
|
||||
@@ -222,7 +222,7 @@ namespace UVtools.Core
|
||||
var layer = this[layerIndex];
|
||||
layer.Index = layerIndex;
|
||||
|
||||
if (property is null)
|
||||
if (property is null || property == nameof(SlicerFile.BottomLayerCount))
|
||||
{
|
||||
layer.ExposureTime = SlicerFile.GetInitialLayerValueOrNormal(layerIndex, SlicerFile.BottomExposureTime, SlicerFile.ExposureTime);
|
||||
layer.LiftHeight = SlicerFile.GetInitialLayerValueOrNormal(layerIndex, SlicerFile.BottomLiftHeight, SlicerFile.LiftHeight);
|
||||
|
||||
@@ -5,7 +5,9 @@ namespace UVtools.Core.Objects
|
||||
{
|
||||
public static class StaticObjects
|
||||
{
|
||||
public static SHA256 Sha256 { get; } = SHA256.Create();
|
||||
public static readonly SHA256 Sha256 = SHA256.Create();
|
||||
|
||||
public static readonly string[] LineBreakCharacters = {"\r\n", "\r", "\n"};
|
||||
|
||||
// Compute the file's hash.
|
||||
public static byte[] GetHashSha256(string filename)
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
<RepositoryUrl>https://github.com/sn4k3/UVtools</RepositoryUrl>
|
||||
<PackageProjectUrl>https://github.com/sn4k3/UVtools</PackageProjectUrl>
|
||||
<Description>MSLA/DLP, file analysis, calibration, repair, conversion and manipulation</Description>
|
||||
<Version>2.5.1</Version>
|
||||
<Version>2.6.0</Version>
|
||||
<Copyright>Copyright © 2020 PTRTECH</Copyright>
|
||||
<PackageIcon>UVtools.png</PackageIcon>
|
||||
<Platforms>AnyCPU;x64</Platforms>
|
||||
@@ -47,6 +47,7 @@
|
||||
<PackageReference Include="BinarySerializer" Version="8.6.0" />
|
||||
<PackageReference Include="Emgu.CV" Version="4.5.1.4349" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
|
||||
<PackageReference Include="Portable.BouncyCastle" Version="1.8.10" />
|
||||
<PackageReference Include="System.Memory" Version="4.5.4" />
|
||||
<PackageReference Include="System.Reflection.TypeExtensions" Version="4.7.0" />
|
||||
</ItemGroup>
|
||||
|
||||
@@ -221,6 +221,9 @@
|
||||
<Component Id="owc0F7CC7ACEA840EC81FADDEE08D4B54C3" Guid="8de4454d-fc84-51cf-d44c-612dcea01607">
|
||||
<File Id="owf0F7CC7ACEA840EC81FADDEE08D4B54C3" Source="$(var.SourceDir)\BinarySerializer.dll" KeyPath="yes" />
|
||||
</Component>
|
||||
<Component Id="owc0D5E901B0EDC9AC66EDED7744C9C0EC4" Guid="bf900338-6ac3-e652-0358-b6c5a433ead1">
|
||||
<File Id="owf0D5E901B0EDC9AC66EDED7744C9C0EC4" Source="$(var.SourceDir)\BouncyCastle.Crypto.dll" KeyPath="yes" />
|
||||
</Component>
|
||||
<Component Id="owc3D4C6D44ECDB03E5FE1F04B44BCF854F" Guid="7357d916-7bf8-aecc-ec52-30bed411500d">
|
||||
<File Id="owf3D4C6D44ECDB03E5FE1F04B44BCF854F" Source="$(var.SourceDir)\clrcompression.dll" KeyPath="yes" />
|
||||
</Component>
|
||||
@@ -1023,6 +1026,9 @@
|
||||
<Component Id="owc696F0AF8084A6AA7624CA0947E245A47" Guid="6aa7d092-d68b-a44d-f2c7-0a590404b19f">
|
||||
<File Id="owf696F0AF8084A6AA7624CA0947E245A47" Source="$(var.SourceDir)\Assets\PrusaSlicer\printer\QIDI Shadow6.0 Pro.ini" KeyPath="yes" />
|
||||
</Component>
|
||||
<Component Id="owc58F08D198616611A088F5E8CA9BAB684" Guid="f0f9d4c3-c4d4-ab8b-ff79-f93dc13fbbbb">
|
||||
<File Id="owf58F08D198616611A088F5E8CA9BAB684" Source="$(var.SourceDir)\Assets\PrusaSlicer\printer\Uniz IBEE.ini" KeyPath="yes" />
|
||||
</Component>
|
||||
<Component Id="owcD0FD9259BE924EB58AE9F7A85AE0A9E8" Guid="360b089c-8765-92db-0c8f-367d80202d8f">
|
||||
<File Id="owfD0FD9259BE924EB58AE9F7A85AE0A9E8" Source="$(var.SourceDir)\Assets\PrusaSlicer\printer\UVtools Prusa SL1.ini" KeyPath="yes" />
|
||||
</Component>
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
<PackageLicenseFile>LICENSE</PackageLicenseFile>
|
||||
<RepositoryUrl>https://github.com/sn4k3/UVtools</RepositoryUrl>
|
||||
<RepositoryType>Git</RepositoryType>
|
||||
<Version>2.5.1</Version>
|
||||
<Version>2.6.0</Version>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
||||
|
||||
Reference in New Issue
Block a user