Merge pull request #1351 from jlewin/master

Use short identifiers for public profiles
This commit is contained in:
johnlewin 2016-09-03 17:27:00 -07:00 committed by GitHub
commit e8a1d27694
8 changed files with 102 additions and 74 deletions

View file

@ -50,7 +50,18 @@ namespace MatterHackers.MatterControl
{
using Agg.Font;
using System.Reflection;
using OemProfileDictionary = Dictionary<string, Dictionary<string, string>>;
public class OemProfileDictionary : Dictionary<string, Dictionary<string, PublicDevice>>
{
}
public class PublicDevice
{
public string DeviceToken { get; set; }
public string ProfileToken { get; set; }
public string ShortProfileID { get; set; }
public string CacheKey => this.ShortProfileID + ProfileManager.ProfileExtension;
}
public abstract class ApplicationView : GuiWidget
{
@ -276,11 +287,7 @@ namespace MatterHackers.MatterControl
/// <returns></returns>
public async static Task<T> LoadCacheableAsync<T>(string cacheKey, string cacheScope, Func<Task<T>> collector, string staticDataFallbackPath = null) where T : class
{
string cacheDirectory = Path.Combine(ApplicationDataStorage.ApplicationUserDataPath, "data", "temp", "cache", cacheScope);
string cachePath = Path.Combine(cacheDirectory, cacheKey);
// Ensure directory exists
Directory.CreateDirectory(cacheDirectory);
string cachePath = CacheablePath(cacheScope, cacheKey);
try
{
@ -289,13 +296,13 @@ namespace MatterHackers.MatterControl
if (item != null)
{
// update cache on success
File.WriteAllText(cachePath, JsonConvert.SerializeObject(item));
File.WriteAllText(cachePath, JsonConvert.SerializeObject(item, Formatting.Indented));
return item;
}
}
catch
{
// fall back to preexisting cache if failed
// Fall back to preexisting cache if failed
}
try
@ -308,7 +315,7 @@ namespace MatterHackers.MatterControl
}
catch
{
//Fallback to Static Data
// Fall back to StaticData
}
try
@ -327,6 +334,19 @@ namespace MatterHackers.MatterControl
return default(T);
}
private static string cacheDirectory = Path.Combine(ApplicationDataStorage.ApplicationUserDataPath, "data", "temp", "cache");
internal static string CacheablePath(string cacheScope, string cacheKey)
{
string scopeDirectory = Path.Combine(cacheDirectory, cacheScope);
// Ensure directory exists
Directory.CreateDirectory(scopeDirectory);
string cachePath = Path.Combine(scopeDirectory, cacheKey);
return cachePath;
}
public void StartSignOut()
{
if (PrinterConnectionAndCommunication.Instance.PrinterIsPrinting

View file

@ -192,15 +192,15 @@ namespace MatterHackers.MatterControl.PrinterControls.PrinterConnections
activeModel = null;
// Select the dictionary containing the printerName->printerToken mappings for the current OEM
Dictionary<string, string> printers;
Dictionary<string, PublicDevice> printers;
if (!OemSettings.Instance.OemProfiles.TryGetValue(activeMake, out printers))
{
// Fall back to an empty dictionary if no match
printers = new Dictionary<string, string>();
printers = new Dictionary<string, PublicDevice>();
}
// Models - sort dictionary results by key and assign to .ListSource
printerModelSelector.ListSource = printers.OrderBy(p => p.Key).ToList();
printerModelSelector.ListSource = printers.OrderBy(p => p.Key).Select(p => new KeyValuePair<string, string>(p.Key, p.Value.ProfileToken)).ToList();
if (printerModelSelector.MenuItems.Count == 1)
{
// SelectIfOnlyOneModel

View file

@ -45,7 +45,6 @@ using System.Threading.Tasks;
namespace MatterHackers.MatterControl.SettingsManagement
{
using Agg.UI;
using OemProfileDictionary = Dictionary<string, Dictionary<string, string>>;
public class OemSettings
{
@ -119,8 +118,8 @@ namespace MatterHackers.MatterControl.SettingsManagement
if (whiteListedItems == null
|| whiteListedItems.Count() == 0)
{
AllOems = new List<KeyValuePair<string, string>>(manufacturers);
return;
// No whitelist means all items
whiteListedItems = manufacturers;
}
var newItems = new List<KeyValuePair<string, string>>();
@ -165,55 +164,49 @@ namespace MatterHackers.MatterControl.SettingsManagement
return;
}
var oemProfiles = await ApplicationController.LoadCacheableAsync<OemProfileDictionary>(
await ApplicationController.LoadCacheableAsync<OemProfileDictionary>(
"oemprofiles.json",
"profiles",
ApplicationController.GetPublicProfileList);
"public-profiles",
async () =>
{
var result = await ApplicationController.GetPublicProfileList();
if (result != null)
{
OemProfiles = result;
// If we failed to get anything from load cacheable don't override potentially populated fields
if (oemProfiles != null)
{
OemProfiles = oemProfiles;
var manufactures = result.Keys.ToDictionary(oem => oem);
SetManufacturers(manufactures);
var manufactures = oemProfiles.Keys.ToDictionary(oem => oem);
SetManufacturers(manufactures);
await DownloadMissingProfiles(syncReport);
}
await DownloadMissingProfiles(syncReport);
}
return result;
});
}
private async Task DownloadMissingProfiles(IProgress<SyncReportType> syncReport)
{
string cacheDirectory = Path.Combine(ApplicationDataStorage.ApplicationUserDataPath, "data", "temp", "cache", "profiles");
SyncReportType reportValue = new SyncReportType();
int index = 0;
foreach (string oem in OemProfiles.Keys)
{
index++;
foreach (string profileKey in OemProfiles[oem].Values)
{
string cacheKey = profileKey + ProfileManager.ProfileExtension;
string cachePath = Path.Combine(cacheDirectory, cacheKey);
string cacheScope = Path.Combine("public-profiles", oem);
index++;
foreach (var publicDevice in OemProfiles[oem].Values)
{
string cachePath = ApplicationController.CacheablePath(cacheScope, publicDevice.CacheKey);
if (!File.Exists(cachePath))
{
var profile = await ApplicationController.DownloadPublicProfileAsync(profileKey);
if(profile != null)
await ProfileManager.LoadOemProfileAsync(publicDevice, oem);
if (syncReport != null)
{
string profileJson = JsonConvert.SerializeObject(profile);
if (!String.IsNullOrEmpty(profileJson))
{
File.WriteAllText(cachePath, profileJson);
}
if (syncReport != null)
{
reportValue.actionLabel = String.Format("Downloading public profiles for {0}...", oem);
reportValue.percComplete = (double)index / OemProfiles.Count;
syncReport.Report(reportValue);
}
reportValue.actionLabel = string.Format("Downloading public profiles for {0}...", oem);
reportValue.percComplete = (double)index / OemProfiles.Count;
syncReport.Report(reportValue);
}
}
}
}
}

View file

@ -329,8 +329,10 @@ namespace MatterHackers.MatterControl.SlicerConfiguration
try
{
string publicProfileDeviceToken = OemSettings.Instance.OemProfiles[profile.Make][profile.Model];
string publicProfileToLoad = Path.Combine(ApplicationDataStorage.ApplicationUserDataPath, "data", "temp", "cache", "profiles", publicProfileDeviceToken + ProfileManager.ProfileExtension);
var publicDevice = OemSettings.Instance.OemProfiles[profile.Make][profile.Model];
string cacheScope = Path.Combine("public-profiles", profile.Make);
string publicProfileToLoad = ApplicationController.CacheablePath(cacheScope, publicDevice.CacheKey);
oemProfile = JsonConvert.DeserializeObject<PrinterSettings>(File.ReadAllText(publicProfileToLoad));
oemProfile.ID = profile.ID;

View file

@ -387,7 +387,12 @@ namespace MatterHackers.MatterControl.SlicerConfiguration
{
string guid = Guid.NewGuid().ToString();
var newProfile = await LoadHttpOemProfile(make, model);
var publicDevice = OemSettings.Instance.OemProfiles[make][model];
// TODO: jlewin - how can we handle lookup failures at this point? Should we throw and check for the exception?
//if (publicDevice == null)
var newProfile = await LoadOemProfileAsync(publicDevice, make);
newProfile.ID = guid;
newProfile.DocumentVersion = PrinterSettings.LatestVersion;
@ -463,28 +468,31 @@ namespace MatterHackers.MatterControl.SlicerConfiguration
"Pink - Light",
};
private async static Task<PrinterSettings> LoadHttpOemProfile(string make, string model)
public async static Task<PrinterSettings> LoadOemProfileAsync(PublicDevice publicDevice, string make)
{
string deviceToken = OemSettings.Instance.OemProfiles[make][model];
string cacheKey = deviceToken + ProfileManager.ProfileExtension;
string cachePath = Path.Combine(ApplicationDataStorage.ApplicationUserDataPath, "data", "temp", "cache", "profiles", cacheKey);
string cacheScope = Path.Combine("public-profiles", make);
string cachePath = ApplicationController.CacheablePath(cacheScope, publicDevice.CacheKey);
return await ApplicationController.LoadCacheableAsync<PrinterSettings>(
cacheKey,
"profiles",
publicDevice.CacheKey,
cacheScope,
async () =>
{
// The collector specifically returns null to ensure LoadCacheable skips writing the
// result to the cache. After this result is returned, it will attempt to load from
// the local cache if the collector yielded no result
if(File.Exists(cachePath))
{
return null;
}
else
{
// If the cache file for the current deviceToken does not exist, attempt to download it
return await ApplicationController.DownloadPublicProfileAsync(deviceToken);
// If the cache file for the current deviceToken does not exist, attempt to download it.
// An http 304 results in a null value and LoadCacheable will then load from the cache
return await ApplicationController.DownloadPublicProfileAsync(publicDevice.ProfileToken);
}
},
Path.Combine("Profiles",make, model + ProfileManager.ProfileExtension));
Path.Combine("Profiles", make, make + ProfileManager.ProfileExtension));
}
public void EnsurePrintersImported()

View file

@ -457,13 +457,17 @@ namespace MatterHackers.MatterControl.SlicerConfiguration
ActiveSliceSettings.Instance.ID = newID;
}
this.ID = newID;
// Ensure the local file with the old ID moves with the new ID change
string existingProfile = ProfilePath;
if (File.Exists(existingProfile))
string existingProfilePath = ProfilePath;
if (File.Exists(existingProfilePath))
{
File.Move(existingProfile, ProfilePath);
// Profile ID change must come after existingProfilePath calculation and before ProfilePath getter
this.ID = newID;
File.Move(existingProfilePath, ProfilePath);
}
else
{
this.ID = newID;
}
if (File.Exists(ProfilePath))

File diff suppressed because one or more lines are too long

View file

@ -57,17 +57,9 @@ namespace MatterControl.Tests.MatterControl
string make = OemSettings.Instance.OemProfiles.First().Key;
string model = OemSettings.Instance.OemProfiles[make].First().Key;
string deviceToken = OemSettings.Instance.OemProfiles[make][model];
string cacheKey = deviceToken + ProfileManager.ProfileExtension;
var publicDevice = OemSettings.Instance.OemProfiles[make][model];
string expectedProfilePath = Path.Combine(ApplicationDataStorage.ApplicationUserDataPath, "Profiles", cacheKey);
if (File.Exists(expectedProfilePath))
{
File.Delete(expectedProfilePath);
}
// Test will fail until mechanism can be created that exposes MHWebservices to vanilla MatterControl or until these tests are moved to MCCentral
var recievedPrinterProfile = await ApplicationController.DownloadPublicProfileAsync(deviceToken);
var recievedPrinterProfile = await ApplicationController.DownloadPublicProfileAsync(publicDevice.ProfileToken);
Assert.IsNotNull(recievedPrinterProfile);