Updater now uses new Versionmap format

This commit is contained in:
2018-11-24 16:10:32 +01:00
parent f60135918c
commit 24b998c20b
5 changed files with 89 additions and 55 deletions

View File

@@ -36,14 +36,14 @@ namespace RothenburgAR.Exhibition
{ {
//throw new System.NotImplementedException(); //throw new System.NotImplementedException();
Dictionary<string, List<Exhibit>> exhibits = new Dictionary<string, List<Exhibit>>(); Dictionary<string, List<ApiExhibit>> exhibits = new Dictionary<string, List<ApiExhibit>>();
var languageDirs = new DirectoryInfo(exhibitionDirectory).GetDirectories().Select(d => d.Name).ToList(); var languageDirs = new DirectoryInfo(exhibitionDirectory).GetDirectories().Select(d => d.Name).ToList();
foreach (var lang in languageDirs) foreach (var lang in languageDirs)
{ {
var metaFilePath = PathHelper.CombinePaths(exhibitionDirectory, lang, "meta.json"); var metaFilePath = PathHelper.CombinePaths(exhibitionDirectory, lang, "meta.json");
if (!File.Exists(metaFilePath)) continue; if (!File.Exists(metaFilePath)) continue;
var exhibitList = JsonConvert.DeserializeObject<List<Exhibit>>(File.ReadAllText(metaFilePath, System.Text.Encoding.UTF8)); var exhibitList = JsonConvert.DeserializeObject<List<ApiExhibit>>(File.ReadAllText(metaFilePath, System.Text.Encoding.UTF8));
exhibits.Add(lang, exhibitList); exhibits.Add(lang, exhibitList);
} }
@@ -65,7 +65,7 @@ namespace RothenburgAR.Exhibition
return resultExhibition; return resultExhibition;
} }
private PreloadedExhibit PreloadExhibit(Dictionary<string, List<Exhibit>> exhibits, string exhibitId) private PreloadedExhibit PreloadExhibit(Dictionary<string, List<ApiExhibit>> exhibits, string exhibitId)
{ {
PreloadedExhibit newExhibit = new PreloadedExhibit(); PreloadedExhibit newExhibit = new PreloadedExhibit();

View File

@@ -31,20 +31,20 @@ namespace RothenburgAR.PointOfInterest
public List<PoiData> PreloadPoi(string poiDirectory) public List<PoiData> PreloadPoi(string poiDirectory)
{ {
List<PoiData> preloadedPois = new List<PoiData>(); List<PoiData> preloadedPois = new List<PoiData>();
Dictionary<string, List<Exhibit>> exhibits = new Dictionary<string, List<Exhibit>>(); Dictionary<string, List<ApiExhibit>> exhibits = new Dictionary<string, List<ApiExhibit>>();
var languageDirs = new DirectoryInfo(poiDirectory).GetDirectories().Select(d => d.Name).ToList(); var languageDirs = new DirectoryInfo(poiDirectory).GetDirectories().Select(d => d.Name).ToList();
foreach (var lang in languageDirs) foreach (var lang in languageDirs)
{ {
var metaFilePath = PathHelper.CombinePaths(poiDirectory, lang, "meta.json"); var metaFilePath = PathHelper.CombinePaths(poiDirectory, lang, "meta.json");
if (!File.Exists(metaFilePath)) continue; if (!File.Exists(metaFilePath)) continue;
var exhibitList = JsonConvert.DeserializeObject<List<Exhibit>>(File.ReadAllText(metaFilePath, System.Text.Encoding.UTF8)); var exhibitList = JsonConvert.DeserializeObject<List<ApiExhibit>>(File.ReadAllText(metaFilePath, System.Text.Encoding.UTF8));
exhibits.Add(lang, exhibitList); exhibits.Add(lang, exhibitList);
} }
var poiIds = exhibits.Values.SelectMany(l => l.SelectMany(e => e.Pois.Select(p => p.Id))).Distinct().ToList(); var poiIds = exhibits.Values.SelectMany(l => l.SelectMany(e => e.Pois.Select(p => p.Id))).Distinct().ToList();
Dictionary<string, List<Poi>> poisPerLang = new Dictionary<string, List<Poi>>(); Dictionary<string, List<ApiPoi>> poisPerLang = new Dictionary<string, List<ApiPoi>>();
exhibits.Keys.ToList().ForEach(k => exhibits.Keys.ToList().ForEach(k =>
poisPerLang.Add(k, exhibits[k].SelectMany(l => l.Pois.Select(p => p)).Distinct().ToList())); poisPerLang.Add(k, exhibits[k].SelectMany(l => l.Pois.Select(p => p)).Distinct().ToList()));

View File

@@ -29,36 +29,39 @@ namespace RothenburgAR.Updater
} }
[Serializable] [Serializable]
public class VersioncheckAnswer public class ApiVersioncheckAnswer
{ {
[JsonProperty("languages")] [JsonProperty("languages")]
public List<string> Languages { get; set; } public List<string> Languages { get; set; }
[JsonProperty("data")] [JsonProperty("data")]
public List<ExhibitionVersion> Data { get; set; } public List<ApiExhibitionVersion> Data { get; set; }
} }
[Serializable] [Serializable]
public class ExhibitionVersion public class ApiExhibitionVersion
{ {
[JsonProperty("id")] [JsonProperty("id")]
public string Id { get; set; } public string Id { get; set; }
[JsonProperty("meta")] [JsonProperty("meta")]
public VersionInfo Meta { get; set; } public ApiVersionInfo Meta { get; set; }
[JsonProperty("tracker")] [JsonProperty("tracker")]
public VersionInfo Tracker { get; set; } public ApiVersionInfo Tracker { get; set; }
} }
[Serializable] [Serializable]
public class VersionInfo public class ApiVersionInfo
{ {
[JsonProperty("status")] [JsonProperty("status")]
public VersionStatus Status { get; set; } public VersionStatus Status { get; set; }
[JsonProperty("updateUrl")] [JsonProperty("updateUrl")]
public string UpdateUrl { get; set; } public string UpdateUrl { get; set; }
[JsonProperty("updateVersion")]
public long UpdateVersion { get; set; }
} }
public enum VersionStatus public enum VersionStatus
@@ -68,7 +71,7 @@ namespace RothenburgAR.Updater
deleted deleted
} }
public class Exhibit public class ApiExhibit
{ {
[JsonProperty("id")] [JsonProperty("id")]
public string Id { get; set; } public string Id { get; set; }
@@ -95,10 +98,10 @@ namespace RothenburgAR.Updater
public long UpdatedTime { get; set; } public long UpdatedTime { get; set; }
[JsonProperty("pois")] [JsonProperty("pois")]
public List<Poi> Pois { get; set; } public List<ApiPoi> Pois { get; set; }
} }
public class Poi public class ApiPoi
{ {
[JsonProperty("id")] [JsonProperty("id")]
public string Id { get; set; } public string Id { get; set; }

View File

@@ -13,6 +13,8 @@ namespace RothenburgAR.Updater
private readonly HttpVerb verb; private readonly HttpVerb verb;
private string uploadData; private string uploadData;
private Dictionary<string, string> headerEntries = new Dictionary<string, string>();
public HttpRequest(String url, HttpVerb verb, String uploadData = null) public HttpRequest(String url, HttpVerb verb, String uploadData = null)
{ {
this.url = url; this.url = url;
@@ -20,17 +22,27 @@ namespace RothenburgAR.Updater
this.uploadData = uploadData; this.uploadData = uploadData;
} }
public HttpRequest WithHeader(string header, string value)
{
headerEntries.Add(header, value);
return this;
}
public HttpHandler Send() public HttpHandler Send()
{ {
Debug.Log(string.Format("{1}-Downloading {0}", url, Time.realtimeSinceStartup)); Debug.Log(string.Format("{1}-Downloading {0}", url, Time.realtimeSinceStartup));
DownloadHandler dl = new DownloadHandlerBuffer(); DownloadHandler dl = new DownloadHandlerBuffer();
UploadHandlerRaw ul = null; UploadHandlerRaw ul = null;
if (uploadData != null) { ul = new UploadHandlerRaw(Encoding.UTF8.GetBytes(uploadData.ToCharArray())); } if (uploadData != null && uploadData != string.Empty)
{
ul = new UploadHandlerRaw(Encoding.UTF8.GetBytes(uploadData.ToCharArray()));
}
string verb = Enum.GetName(typeof(HttpVerb), this.verb); string verb = Enum.GetName(typeof(HttpVerb), this.verb);
UnityWebRequest wr = new UnityWebRequest(url, verb, dl, ul); UnityWebRequest wr = new UnityWebRequest(url, verb, dl, ul);
wr.SetRequestHeader("Content-Type", "application/json;charset=UTF-8"); wr.SetRequestHeader("Content-Type", "application/json;charset=UTF-8");
foreach (var entry in headerEntries) { wr.SetRequestHeader(entry.Key, entry.Value); }
var operation = wr.SendWebRequest(); var operation = wr.SendWebRequest();
@@ -38,7 +50,7 @@ namespace RothenburgAR.Updater
} }
} }
public enum HttpVerb public enum HttpVerb
{ {
GET, GET,
POST, POST,
@@ -51,7 +63,7 @@ namespace RothenburgAR.Updater
public UploadHandler Upload { get; set; } public UploadHandler Upload { get; set; }
public DownloadHandler Download { get; set; } public DownloadHandler Download { get; set; }
public UnityWebRequest Request { get; set; } public UnityWebRequest Request { get; set; }
public UnityWebRequestAsyncOperation Operation {get;set;} public UnityWebRequestAsyncOperation Operation { get; set; }
public bool IsDone public bool IsDone
{ {

View File

@@ -20,7 +20,7 @@ namespace RothenburgAR.Updater
private readonly float afterDownloadWaitTime = 10f; private readonly float afterDownloadWaitTime = 10f;
public VersioncheckAnswer VersionAnswer { get; set; } public ApiVersioncheckAnswer VersionAnswer { get; set; }
private List<HttpHandler> httpHandlers = new List<HttpHandler>(); private List<HttpHandler> httpHandlers = new List<HttpHandler>();
private LogFileHandler logFileHandler; private LogFileHandler logFileHandler;
@@ -69,8 +69,7 @@ namespace RothenburgAR.Updater
Debug.Log(http.Download.text); Debug.Log(http.Download.text);
VersionAnswer = JsonConvert.DeserializeObject<VersioncheckAnswer>(http.Download.text); VersionAnswer = JsonConvert.DeserializeObject<ApiVersioncheckAnswer>(http.Download.text);
//VersionAnswer = JsonConvert.DeserializeObject<VersioncheckAnswer>(@"{""languages"":[""de"",""en""],""data"":[{""id"":""006e164c-5e31-4ddf-adf5-df7016c8b3a8"",""meta"":{""status"":""ok"",""updateUrl"":""https://lambdalike.pa.kaim.network/meta/006e164c-5e31-4ddf-adf5-df7016c8b3a7/{lang}""},""tracker"":{""status"":""ok"",""updateUrl"":""https://lambdalike.pa.kaim.network/meta/006e164c-5e31-4ddf-adf5-df7016c8b3a7/{lang}""}},{""id"":""006e164c-5e31-4ddf-adf5-df7016c8b3a7"",""meta"":{""status"":""updated"",""updateUrl"":""https://lambdalike.pa.kaim.network/meta/006e164c-5e31-4ddf-adf5-df7016c8b3a7/{lang}""},""tracker"":{""status"":""ok"",""updateUrl"":""https://lambdalike.pa.kaim.network/meta/006e164c-5e31-4ddf-adf5-df7016c8b3a7/{lang}""}}]}");
Debug.Log(string.Format("{1}-DONE with {0}", ApiInfo.VersionCheckEndpoint, Time.realtimeSinceStartup)); Debug.Log(string.Format("{1}-DONE with {0}", ApiInfo.VersionCheckEndpoint, Time.realtimeSinceStartup));
var answer = VersionAnswer; var answer = VersionAnswer;
@@ -106,24 +105,15 @@ namespace RothenburgAR.Updater
} }
var exhibitionDirs = rootDir.GetDirectories().ToList(); var exhibitionDirs = rootDir.GetDirectories().ToList();
exhibitionDirs.ForEach(dir =>
foreach (var dir in exhibitionDirs)
{ {
var subdir = dir.GetDirectories().ToList().FirstOrDefault(); var versionFilePath = Path.Combine(dir.FullName, "version.txt");
if (subdir == null) return; if (!File.Exists(versionFilePath)) continue;
var metaFilePath = Path.Combine(subdir.FullName, "meta.json"); var version = long.Parse(File.ReadAllText(versionFilePath));
if (!File.Exists(metaFilePath)) return; result += @"""{id}"":""{version}"",".Replace("{id}", dir.Name).Replace("{version}", version.ToString());
};
var exhibits = JsonConvert.DeserializeObject<List<Exhibit>>(File.ReadAllText(metaFilePath));
long newestVersion = 0;
foreach (var exhibit in exhibits)
{
newestVersion = Math.Max(newestVersion, exhibit.UpdatedTime);
//result += @"""{id}"":""{version}"",".Replace("{id}", exhibit.Id).Replace("{version}", exhibit.UpdatedTime.ToString());
}
result += @"""{id}"":""{version}"",".Replace("{id}", dir.Name).Replace("{version}", newestVersion.ToString());
});
result = result.Substring(0, result.Length - 1) + "}"; result = result.Substring(0, result.Length - 1) + "}";
return result; return result;
@@ -134,7 +124,7 @@ namespace RothenburgAR.Updater
/* /*
* dir structure: * dir structure:
* data * data
* exhibitions * exhibition
* id * id
* tracker.dat * tracker.dat
* tracker.xml * tracker.xml
@@ -181,20 +171,28 @@ namespace RothenburgAR.Updater
deletedData.ForEach(d => DeleteExhibition(d)); deletedData.ForEach(d => DeleteExhibition(d));
} }
private void DeleteExhibition(ExhibitionVersion d) private void DeleteExhibition(ApiExhibitionVersion exhibition)
{ {
//TODO implement DeleteExhibition var path = Path.Combine(PathHelper.ExhibitionPath, exhibition.Id);
throw new NotImplementedException(); Directory.Delete(path, true);
} }
private void UpdateMeta(ExhibitionVersion exhibition) private void UpdateMeta(ApiExhibitionVersion exhibition)
{ {
var versionData = new UpdateVersionFileCoroutineData
{
path = PathHelper.CombinePaths(PathHelper.ExhibitionPath, exhibition.Id, "version.txt"),
httpHandlers = new List<HttpHandler>(),
version = exhibition.Meta.UpdateVersion.ToString()
};
foreach (var lang in VersionAnswer.Languages) foreach (var lang in VersionAnswer.Languages)
{ {
var path = PathHelper.CombinePaths(PathHelper.ExhibitionPath, exhibition.Id, lang); var path = PathHelper.CombinePaths(PathHelper.ExhibitionPath, exhibition.Id, lang);
var url = exhibition.Meta.UpdateUrl.Replace("{lang}", lang); var url = exhibition.Meta.UpdateUrl.Replace("{lang}", lang);
var http = new HttpRequest(url, HttpVerb.GET).Send(); var http = new HttpRequest(url, HttpVerb.GET).Send();
httpHandlers.Add(http); httpHandlers.Add(http);
versionData.httpHandlers.Add(http);
http.Operation.completed += ar => http.Operation.completed += ar =>
{ {
@@ -211,7 +209,7 @@ namespace RothenburgAR.Updater
File.WriteAllText(Path.Combine(path, "meta.json"), http.Download.text, System.Text.Encoding.UTF8); File.WriteAllText(Path.Combine(path, "meta.json"), http.Download.text, System.Text.Encoding.UTF8);
Debug.Log(string.Format("{1}-DONE with {0}", url, Time.realtimeSinceStartup)); Debug.Log(string.Format("{1}-DONE with {0}", url, Time.realtimeSinceStartup));
var exhibits = JsonConvert.DeserializeObject<List<Exhibit>>(http.Download.text); var exhibits = JsonConvert.DeserializeObject<List<ApiExhibit>>(http.Download.text);
foreach (var exhibit in exhibits) foreach (var exhibit in exhibits)
{ {
UpdateMedia(exhibit); UpdateMedia(exhibit);
@@ -219,26 +217,46 @@ namespace RothenburgAR.Updater
}; };
} }
StartCoroutine("UpdateVersionFileCoroutine", versionData);
} }
private void UpdateMedia(Exhibit exhibit) private IEnumerator UpdateVersionFileCoroutine(UpdateVersionFileCoroutineData versionData)
{
// updates version file only if all sub files were downloaded successfully
yield return new WaitUntil(() => versionData.httpHandlers.All(h => h.IsDone));
if (versionData.httpHandlers.Any(http => http.Request.isNetworkError || http.Request.isHttpError)) yield break;
File.WriteAllText(versionData.path, versionData.version);
}
private class UpdateVersionFileCoroutineData
{
public List<HttpHandler> httpHandlers;
public string path;
public string version;
}
private void UpdateMedia(ApiExhibit exhibit)
{ {
var mediaIDs = exhibit.Pois.Select(p => p.MediaId).Except(new List<string> { null }).ToList(); var mediaIDs = exhibit.Pois.Select(p => p.MediaId).Except(new List<string> { null }).ToList();
foreach (var mediaId in mediaIDs) foreach (var mediaId in mediaIDs)
{ {
//System.Security.Cryptography.MD5CryptoServiceProvider
//System.Security.Cryptography.SHA1CryptoServiceProvider
//System.Security.Cryptography.SHA256
var path = PathHelper.CombinePaths(PathHelper.MediaPath, mediaId); var path = PathHelper.CombinePaths(PathHelper.MediaPath, mediaId);
var filepath = Path.Combine(path, "media.zip"); var filepath = Path.Combine(path, "media.zip");
//TODO cancel download if unnecessary, how to check if unnecessary? // create dir if nonexistent
if (File.Exists(filepath)) continue;
// create file and dir if nonexistent
if (!Directory.Exists(path)) Directory.CreateDirectory(path); if (!Directory.Exists(path)) Directory.CreateDirectory(path);
if (!File.Exists(filepath)) File.Create(filepath).Close();
var url = ApiInfo.FileEndpoint.Replace("{id}", mediaId); var url = ApiInfo.FileEndpoint.Replace("{id}", mediaId);
var http = new HttpRequest(url, HttpVerb.GET).Send(); var http = new HttpRequest(url, HttpVerb.GET)
.WithHeader("ETag", "")
.Send();
httpHandlers.Add(http); httpHandlers.Add(http);
http.Operation.completed += ar => http.Operation.completed += ar =>
@@ -248,11 +266,12 @@ namespace RothenburgAR.Updater
return; return;
} }
var x = http;
//TODO unzip //TODO unzip
var type = http.Request.GetResponseHeader("Content-Type"); var type = http.Request.GetResponseHeader("Content-Type");
File.WriteAllBytes(filepath, http.Download.data); File.WriteAllBytes(filepath, http.Download.data);
Debug.Log(string.Format("{1}-DONE with {0}", url, Time.realtimeSinceStartup)); Debug.Log(string.Format("{1}-DONE with {0}", url, Time.realtimeSinceStartup));
}; };
} }
} }
@@ -280,7 +299,7 @@ namespace RothenburgAR.Updater
return false; return false;
} }
private void UpdateTracker(ExhibitionVersion exhibition) private void UpdateTracker(ApiExhibitionVersion exhibition)
{ {
//TODO test UpdateTracker //TODO test UpdateTracker
var path = PathHelper.CombinePaths(PathHelper.ExhibitionPath, exhibition.Id); var path = PathHelper.CombinePaths(PathHelper.ExhibitionPath, exhibition.Id);
@@ -299,7 +318,7 @@ namespace RothenburgAR.Updater
{ {
Directory.CreateDirectory(path); Directory.CreateDirectory(path);
} }
//TODO unzip, should be tracker.xml and tracker.dat files //TODO unzip, should be tracker.xml and tracker.dat files
var type = http.Request.GetResponseHeader("Content-Type"); var type = http.Request.GetResponseHeader("Content-Type");
File.WriteAllBytes(Path.Combine(path, "tracker.zip"), http.Download.data); File.WriteAllBytes(Path.Combine(path, "tracker.zip"), http.Download.data);