364 lines
No EOL
10 KiB
C#
364 lines
No EOL
10 KiB
C#
/*
|
|
Copyright (c) 2016, 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 Newtonsoft.Json;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Runtime.Serialization;
|
|
using System;
|
|
using System.IO;
|
|
using Newtonsoft.Json.Linq;
|
|
using System.Text;
|
|
using System.Collections.ObjectModel;
|
|
using MatterHackers.MatterControl.DataStorage;
|
|
using MatterHackers.MatterControl.SettingsManagement;
|
|
|
|
namespace MatterHackers.MatterControl.SlicerConfiguration
|
|
{
|
|
public class PrinterSettings
|
|
{
|
|
// Latest version should be 2016|06|08|1
|
|
// Year|month|day|versionForDay (to support multiple revisions on a given day)
|
|
public static int LatestVersion { get; } = 201606271;
|
|
|
|
private static PrinterSettingsLayer baseLayerCache;
|
|
|
|
public int DocumentVersion { get; set; }
|
|
|
|
public string ID { get; set; }
|
|
|
|
|
|
[JsonIgnore]
|
|
internal PrinterSettingsLayer QualityLayer { get; private set; }
|
|
|
|
[JsonIgnore]
|
|
internal PrinterSettingsLayer MaterialLayer { get; private set; }
|
|
|
|
public PrinterSettings()
|
|
{
|
|
}
|
|
|
|
public List<GCodeMacro> Macros { get; set; } = new List<GCodeMacro>();
|
|
|
|
[OnDeserialized]
|
|
internal void OnDeserializedMethod(StreamingContext context)
|
|
{
|
|
QualityLayer = GetQualityLayer(ActiveQualityKey);
|
|
|
|
string materialSettingsKey = GetMaterialPresetKey(0);
|
|
if (!string.IsNullOrEmpty(materialSettingsKey))
|
|
{
|
|
MaterialLayer = GetMaterialLayer(materialSettingsKey);
|
|
}
|
|
}
|
|
|
|
public PrinterSettingsLayer OemLayer { get; set; }
|
|
|
|
internal PrinterSettingsLayer GetMaterialLayer(string layerID)
|
|
{
|
|
if (string.IsNullOrEmpty(layerID))
|
|
{
|
|
return null;
|
|
}
|
|
|
|
return MaterialLayers.Where(layer => layer.LayerID == layerID).FirstOrDefault();
|
|
}
|
|
|
|
private PrinterSettingsLayer GetQualityLayer(string layerID)
|
|
{
|
|
return QualityLayers.Where(layer => layer.LayerID == layerID).FirstOrDefault();
|
|
}
|
|
|
|
public string ActiveQualityKey
|
|
{
|
|
get
|
|
{
|
|
return GetValue("active_quality_key");
|
|
}
|
|
internal set
|
|
{
|
|
SetValue("active_quality_key", value);
|
|
QualityLayer = GetQualityLayer(value);
|
|
Save();
|
|
}
|
|
}
|
|
|
|
public string GetMaterialPresetKey(int extruderIndex)
|
|
{
|
|
if (extruderIndex >= MaterialSettingsKeys.Count)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
return MaterialSettingsKeys[extruderIndex];
|
|
}
|
|
|
|
public void SetMaterialPreset(int extruderIndex, string materialKey)
|
|
{
|
|
if (extruderIndex >= PrinterCommunication.PrinterConnectionAndCommunication.MAX_EXTRUDERS)
|
|
{
|
|
throw new ArgumentOutOfRangeException("Requested extruder index is outside of bounds: " + extruderIndex);
|
|
}
|
|
|
|
// TODO: This should really be in SettingsProfile and should be run when the extruder count changes
|
|
if (MaterialSettingsKeys.Count <= extruderIndex)
|
|
{
|
|
var resizedArray = new string[extruderIndex + 1];
|
|
MaterialSettingsKeys.CopyTo(resizedArray);
|
|
MaterialSettingsKeys = new List<string>(resizedArray);
|
|
}
|
|
|
|
MaterialSettingsKeys[extruderIndex] = materialKey;
|
|
|
|
if (extruderIndex == 0)
|
|
{
|
|
MaterialLayer = GetMaterialLayer(materialKey);
|
|
ApplicationController.Instance.ReloadAdvancedControlsPanel();
|
|
}
|
|
|
|
Save();
|
|
}
|
|
|
|
public List<string> MaterialSettingsKeys { get; set; } = new List<string>();
|
|
|
|
private string GenerateSha1()
|
|
{
|
|
// Maybe be UTF8 encoded, may not...
|
|
using (var fileStream = new FileStream(DocumentPath, FileMode.Open))
|
|
using (var bufferedStream = new BufferedStream(fileStream, 1200000))
|
|
{
|
|
return GenerateSha1(bufferedStream);
|
|
}
|
|
}
|
|
|
|
private string GenerateSha1(Stream stream)
|
|
{
|
|
// var timer = Stopwatch.StartNew();
|
|
using (var sha1 = System.Security.Cryptography.SHA1.Create())
|
|
{
|
|
byte[] hash = sha1.ComputeHash(stream);
|
|
string SHA1 = BitConverter.ToString(hash).Replace("-", String.Empty);
|
|
|
|
// Console.WriteLine("{0} {1} {2}", SHA1, timer.ElapsedMilliseconds, filePath);
|
|
return SHA1;
|
|
}
|
|
}
|
|
|
|
private string DocumentPath => ProfileManager.Instance.ProfilePath(this.ID);
|
|
|
|
internal void Save()
|
|
{
|
|
string json = JsonConvert.SerializeObject(this, Formatting.Indented);
|
|
|
|
// SHA1 value is based on UTF8 encoded file contents
|
|
using (var memoryStream = new MemoryStream(Encoding.UTF8.GetBytes(json)))
|
|
{
|
|
string sha1 = GenerateSha1(memoryStream);
|
|
this.UserLayer["profile_sha1"] = sha1;
|
|
|
|
var printerInfo = ProfileManager.Instance[this.ID];
|
|
if (printerInfo != null)
|
|
{
|
|
printerInfo.SHA1 = sha1;
|
|
printerInfo.IsDirty = true;
|
|
ProfileManager.Instance.Save();
|
|
}
|
|
}
|
|
|
|
File.WriteAllText(DocumentPath, json);
|
|
|
|
if (ActiveSliceSettings.Instance.ID == this.ID)
|
|
{
|
|
ActiveSliceSettings.ActiveProfileModified.CallEvents(null, null);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// User settings overrides
|
|
/// </summary>
|
|
public PrinterSettingsLayer UserLayer { get; } = new PrinterSettingsLayer();
|
|
//
|
|
public static PrinterSettings LoadFile(string printerProfilePath)
|
|
{
|
|
|
|
JObject jObject;
|
|
try
|
|
{
|
|
jObject = JObject.Parse(File.ReadAllText(printerProfilePath));
|
|
}
|
|
catch
|
|
{
|
|
return RecoverProfile(printerProfilePath);
|
|
}
|
|
|
|
int documentVersion = jObject?.GetValue("DocumentVersion")?.Value<int>() ?? 0;
|
|
|
|
if (documentVersion < PrinterSettings.LatestVersion)
|
|
{
|
|
printerProfilePath = ProfileMigrations.MigrateDocument(printerProfilePath, documentVersion);
|
|
}
|
|
|
|
// Reload the document with the new schema
|
|
try
|
|
{
|
|
return JsonConvert.DeserializeObject<PrinterSettings>(File.ReadAllText(printerProfilePath));
|
|
}
|
|
catch
|
|
{
|
|
return RecoverProfile(printerProfilePath);
|
|
}
|
|
}
|
|
|
|
public static PrinterSettings RecoverProfile(string printerProfilePath)
|
|
{
|
|
string profileKey = Path.GetFileNameWithoutExtension(printerProfilePath);
|
|
var profile = ProfileManager.Instance[profileKey];
|
|
string publicProfileDeviceToken = OemSettings.Instance.OemProfiles[profile.Make][profile.Model];
|
|
string publicProfileToLoad = Path.Combine(ApplicationDataStorage.ApplicationUserDataPath, "data", "temp", "cache", "profiles") + "\\" + publicProfileDeviceToken + ".json";
|
|
|
|
var oemProfile = JsonConvert.DeserializeObject<PrinterSettings>(File.ReadAllText(publicProfileToLoad));
|
|
oemProfile.ID = profile.ID;
|
|
oemProfile.SetValue(SettingsKey.printer_name, profile.Name);
|
|
oemProfile.DocumentVersion = PrinterSettings.LatestVersion;
|
|
|
|
var profileHelper = new SettingsProfile(oemProfile);
|
|
profileHelper.SetComPort(profile.ComPort);
|
|
profileHelper.SaveChanges();
|
|
|
|
return oemProfile;
|
|
}
|
|
|
|
// TODO: Hookup OEM layers
|
|
/// <summary>
|
|
/// Should contain both user created and oem specified material layers
|
|
/// </summary>
|
|
public ObservableCollection<PrinterSettingsLayer> MaterialLayers { get; } = new ObservableCollection<PrinterSettingsLayer>();
|
|
|
|
// TODO: Hookup OEM layers
|
|
/// <summary>
|
|
/// Should contain both user created and oem specified quality layers
|
|
/// </summary>
|
|
public ObservableCollection<PrinterSettingsLayer> QualityLayers { get; } = new ObservableCollection<PrinterSettingsLayer>();
|
|
|
|
///<summary>
|
|
///Returns the settings value at the 'top' of the stack
|
|
///</summary>
|
|
public string GetValue(string sliceSetting, IEnumerable<PrinterSettingsLayer> layerCascade = null)
|
|
{
|
|
if (layerCascade == null)
|
|
{
|
|
layerCascade = defaultLayerCascade;
|
|
}
|
|
|
|
foreach (PrinterSettingsLayer layer in layerCascade)
|
|
{
|
|
string value;
|
|
if (layer.TryGetValue(sliceSetting, out value))
|
|
{
|
|
return value;
|
|
}
|
|
}
|
|
|
|
return "";
|
|
}
|
|
|
|
[JsonIgnore]
|
|
public PrinterSettingsLayer BaseLayer
|
|
{
|
|
get
|
|
{
|
|
if (baseLayerCache == null)
|
|
{
|
|
baseLayerCache = SliceSettingsOrganizer.Instance.GetDefaultSettings();
|
|
}
|
|
|
|
return baseLayerCache;
|
|
}
|
|
|
|
internal set
|
|
{
|
|
baseLayerCache = value;
|
|
}
|
|
}
|
|
|
|
private IEnumerable<PrinterSettingsLayer> defaultLayerCascade
|
|
{
|
|
get
|
|
{
|
|
if (this.UserLayer != null)
|
|
{
|
|
yield return this.UserLayer;
|
|
}
|
|
|
|
if (this.MaterialLayer != null)
|
|
{
|
|
yield return this.MaterialLayer;
|
|
}
|
|
|
|
if (this.QualityLayer != null)
|
|
{
|
|
yield return this.QualityLayer;
|
|
}
|
|
|
|
if (this.OemLayer != null)
|
|
{
|
|
yield return this.OemLayer;
|
|
}
|
|
|
|
yield return this.BaseLayer;
|
|
}
|
|
}
|
|
|
|
internal void SetValue(string settingsKey, string settingsValue, PrinterSettingsLayer layer = null)
|
|
{
|
|
var persistenceLayer = layer ?? UserLayer;
|
|
|
|
// If the setting exists and is set the requested value, exit without setting or saving
|
|
string existingValue;
|
|
if (persistenceLayer.TryGetValue(settingsKey, out existingValue) && existingValue == settingsValue)
|
|
{
|
|
return;
|
|
}
|
|
|
|
// Otherwise, set and save
|
|
persistenceLayer[settingsKey] = settingsValue;
|
|
Save();
|
|
}
|
|
|
|
internal void ClearValue(string sliceSetting, PrinterSettingsLayer layer = null)
|
|
{
|
|
var persistenceLayer = layer ?? UserLayer;
|
|
if (persistenceLayer.ContainsKey(sliceSetting))
|
|
{
|
|
persistenceLayer.Remove(sliceSetting);
|
|
Save();
|
|
}
|
|
}
|
|
}
|
|
} |