From 87953204165db0ed7b9401709a8e76122e4db2f4 Mon Sep 17 00:00:00 2001 From: Matt Date: Sat, 18 Aug 2018 18:33:20 +0200 Subject: [PATCH] Implemented remainder of update procedure --- .../RothenburgAR/Scripts/Common/PathHelper.cs | 15 +++ .../RothenburgAR/Scripts/Updater/ApiInfo.cs | 85 +++++++++++--- .../Scripts/Updater/HttpHandler.cs | 16 ++- .../Scripts/Updater/UpdaterBehaviour.cs | 109 +++++++++++++++--- Assets/updaterScene.unity | 4 +- ProjectSettings/EditorBuildSettings.asset | 3 + 6 files changed, 194 insertions(+), 38 deletions(-) diff --git a/Assets/RothenburgAR/Scripts/Common/PathHelper.cs b/Assets/RothenburgAR/Scripts/Common/PathHelper.cs index 5504718..1f02c17 100644 --- a/Assets/RothenburgAR/Scripts/Common/PathHelper.cs +++ b/Assets/RothenburgAR/Scripts/Common/PathHelper.cs @@ -20,6 +20,11 @@ namespace RothenburgAR.Common get { return Path.Combine(DataPath, "exhibition"); } } + public static string MediaPath + { + get { return Path.Combine(DataPath, "media"); } + } + public static bool DataPathExists { get { return Directory.Exists(DataPath); } @@ -52,5 +57,15 @@ namespace RothenburgAR.Common return tempFolder; } + + public static string CombinePaths(params string[] paths) + { + string result = string.Empty; + foreach (var part in paths) + { + result = Path.Combine(result, part); + } + return result; + } } } \ No newline at end of file diff --git a/Assets/RothenburgAR/Scripts/Updater/ApiInfo.cs b/Assets/RothenburgAR/Scripts/Updater/ApiInfo.cs index c348f5d..c3ce10e 100644 --- a/Assets/RothenburgAR/Scripts/Updater/ApiInfo.cs +++ b/Assets/RothenburgAR/Scripts/Updater/ApiInfo.cs @@ -1,5 +1,6 @@ using System.Collections.Generic; using System; +using Newtonsoft.Json; namespace RothenburgAR.Updater { @@ -30,6 +31,7 @@ namespace RothenburgAR.Updater [Serializable] public class VersioncheckAnswer { + [JsonProperty] public List languages { get; set; } public List data { get; set; } } @@ -37,16 +39,24 @@ namespace RothenburgAR.Updater [Serializable] public class ExhibitionVersion { - public string id { get; set; } - public VersionInfo meta { get; set; } - public VersionInfo tracker { get; set; } + [JsonProperty("id")] + public string Id { get; set; } + + [JsonProperty("meta")] + public VersionInfo Meta { get; set; } + + [JsonProperty("tracker")] + public VersionInfo Tracker { get; set; } } [Serializable] public class VersionInfo { - public VersionStatus status { get; set; } - public string updateUrl { get; set; } + [JsonProperty("status")] + public VersionStatus Status { get; set; } + + [JsonProperty("updateUrl")] + public string UpdateUrl { get; set; } } public enum VersionStatus @@ -56,17 +66,60 @@ namespace RothenburgAR.Updater deleted } - [Serializable] - public class ExhibitionData + public class Exhibit { - public string title { get; set; } - public string description { get; set; } - public List tags { get; set; } - public List exhibitionIds { get; set; } - public string mediaId { get; set; } - public object createdTime { get; set; } - public object updatedTime { get; set; } - public string id { get; set; } - public List pois { get; set; } + [JsonProperty("id")] + public string Id { get; set; } + + [JsonProperty("title")] + public string Title { get; set; } + + [JsonProperty("description")] + public string Description { get; set; } + + [JsonProperty("tags")] + public List Tags { get; set; } + + [JsonProperty("exhibitionIds")] + public List ExhibitionIds { get; set; } + + [JsonProperty("mediaId")] + public string MediaId { get; set; } + + [JsonProperty("createdTime")] + public long CreatedTime { get; set; } + + [JsonProperty("updatedTime")] + public long UpdatedTime { get; set; } + + [JsonProperty("pois")] + public List Pois { get; set; } + } + + public class Poi + { + [JsonProperty("id")] + public string Id { get; set; } + + [JsonProperty("title")] + public string Title { get; set; } + + [JsonProperty("description")] + public string Description { get; set; } + + [JsonProperty("imageId")] + public string ImageId { get; set; } + + [JsonProperty("x")] + public double X { get; set; } + + [JsonProperty("y")] + public double Y { get; set; } + + [JsonProperty("createdTime")] + public long CreatedTime { get; set; } + + [JsonProperty("updatedTime")] + public long UpdatedTime { get; set; } } } \ No newline at end of file diff --git a/Assets/RothenburgAR/Scripts/Updater/HttpHandler.cs b/Assets/RothenburgAR/Scripts/Updater/HttpHandler.cs index b305484..11e352a 100644 --- a/Assets/RothenburgAR/Scripts/Updater/HttpHandler.cs +++ b/Assets/RothenburgAR/Scripts/Updater/HttpHandler.cs @@ -12,7 +12,7 @@ namespace RothenburgAR.Updater private HttpVerb verb; private string uploadData; - public HttpRequest(String url, HttpVerb verb, String uploadData = null) + public HttpRequest(String url, HttpVerb verb, String uploadData = null) { this.url = url; this.verb = verb; @@ -21,9 +21,10 @@ namespace RothenburgAR.Updater public HttpHandler send() { - UploadHandlerRaw ul = new UploadHandlerRaw(Encoding.UTF8.GetBytes(uploadData.ToCharArray())); DownloadHandler dl = new DownloadHandlerBuffer(); - + UploadHandlerRaw ul = null; + if (uploadData != null) { ul = new UploadHandlerRaw(Encoding.UTF8.GetBytes(uploadData.ToCharArray())); } + string verb = Enum.GetName(typeof(HttpVerb), this.verb); UnityWebRequest wr = new UnityWebRequest(url, verb, dl, ul); @@ -50,6 +51,15 @@ namespace RothenburgAR.Updater public UnityWebRequest request { get; set; } public UnityWebRequestAsyncOperation operation {get;set;} + public bool IsDone + { + get + { + //TODO read documentation + return operation.isDone && request.isDone; + } + } + public HttpHandler(UploadHandler upload, DownloadHandler download, UnityWebRequest request, UnityWebRequestAsyncOperation operation) { this.upload = upload; diff --git a/Assets/RothenburgAR/Scripts/Updater/UpdaterBehaviour.cs b/Assets/RothenburgAR/Scripts/Updater/UpdaterBehaviour.cs index 4bca609..dc6e92f 100644 --- a/Assets/RothenburgAR/Scripts/Updater/UpdaterBehaviour.cs +++ b/Assets/RothenburgAR/Scripts/Updater/UpdaterBehaviour.cs @@ -13,6 +13,8 @@ namespace RothenburgAR.Updater { public VersioncheckAnswer VersionAnswer { get; set; } + private List httpHandlers = new List(); + void Start() { /* TODO: allg. fragen @@ -20,6 +22,8 @@ namespace RothenburgAR.Updater oder beim update auswählen lassen, welche kommen sollen */ + FindObjectsOfType().First().enabled = true; + if (Application.internetReachability == NetworkReachability.NotReachable) { // just continue to app @@ -36,18 +40,23 @@ namespace RothenburgAR.Updater //TODO generate versionmap (i guess by crawling all subdirs of /exhibitions) string versionMap = "[]"; - HttpHandler httpHandler = new HttpRequest(ApiInfo.VersionCheckEndpoint, HttpVerb.POST, versionMap).send(); + HttpHandler http = new HttpRequest(ApiInfo.VersionCheckEndpoint, HttpVerb.POST, versionMap).send(); + httpHandlers.Add(http); // httpHandler.operation.progress needs to be polled - httpHandler.operation.completed += ar => + http.operation.completed += ar => { - //TODO check for network errors/timeouts (and find out if operation.completed() is the right place for that) - Debug.Log(httpHandler.download.text); + if (CheckNetworkErrors(http)) + { + return; + } + + Debug.Log(http.download.text); //versionAnswer = JsonConvert.DeserializeObject(httpHandler.download.text); - VersionAnswer = JsonConvert.DeserializeObject(@"{""data"":[{""id"":""a"",""meta"":{""status"":""ok"",""updateUrl"":""https://lambdalike.pa.kaim.network/meta/006e164c-5e31-4ddf-adf5-df7016c8b3a7/de""},""tracker"":""meta"":{""status"":""ok"",""updateUrl"":""https://lambdalike.pa.kaim.network/meta/006e164c-5e31-4ddf-adf5-df7016c8b3a7/de""}},{""id"":""b"",""meta"":{""status"":""updated"",""updateUrl"":""https://lambdalike.pa.kaim.network/meta/006e164c-5e31-4ddf-adf5-df7016c8b3a7/de""},""tracker"":""meta"":{""status"":""ok"",""updateUrl"":""https://lambdalike.pa.kaim.network/meta/006e164c-5e31-4ddf-adf5-df7016c8b3a7/de""}}]}"); + VersionAnswer = JsonConvert.DeserializeObject(@"{""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}""}}]}"); - if (VersionAnswer.data.TrueForAll(d => d.meta.status == VersionStatus.ok && d.tracker.status == VersionStatus.ok)) + if (VersionAnswer.data.TrueForAll(d => d.Meta.Status == VersionStatus.ok && d.Tracker.Status == VersionStatus.ok)) { // no updates required, continue to app LoadMainScene(); @@ -89,12 +98,12 @@ namespace RothenburgAR.Updater //TODO write languages to file the app can read - var updatedMeta = VersionAnswer.data.Where(d => d.meta.status == VersionStatus.updated).ToList(); - var updatedTracker = VersionAnswer.data.Where(d => d.tracker.status == VersionStatus.updated).ToList(); + var updatedMeta = VersionAnswer.data.Where(d => d.Meta.Status == VersionStatus.updated).ToList(); + var updatedTracker = VersionAnswer.data.Where(d => d.Tracker.Status == VersionStatus.updated).ToList(); updatedMeta.Union(updatedTracker).ToList().ForEach(updatedExhibition => { // create exhibition directories - var path = Path.Combine(PathHelper.ExhibitionPath, updatedExhibition.id); + var path = Path.Combine(PathHelper.ExhibitionPath, updatedExhibition.Id); if (!Directory.Exists(path)) { Directory.CreateDirectory(path); @@ -104,8 +113,8 @@ namespace RothenburgAR.Updater updatedMeta.ForEach(d => UpdateMeta(d)); updatedTracker.ForEach(d => UpdateTracker(d)); - var deletedMeta = VersionAnswer.data.Where(d => d.meta.status == VersionStatus.deleted).ToList(); - var deletedTracker = VersionAnswer.data.Where(d => d.tracker.status == VersionStatus.deleted).ToList(); + var deletedMeta = VersionAnswer.data.Where(d => d.Meta.Status == VersionStatus.deleted).ToList(); + var deletedTracker = VersionAnswer.data.Where(d => d.Tracker.Status == VersionStatus.deleted).ToList(); //TODO figure out if you can delete a tracker but not the meta (or vice versa) } @@ -113,12 +122,18 @@ namespace RothenburgAR.Updater { foreach (var lang in VersionAnswer.languages) { - var path = Path.Combine(PathHelper.ExhibitionPath, lang); - var url = ApiInfo.ExhibitionEndpoint.Replace("{lang}", lang).Replace("{id}", exhibition.id); + var path = PathHelper.CombinePaths(PathHelper.ExhibitionPath, exhibition.Id, lang); + var url = exhibition.Meta.UpdateUrl.Replace("{lang}", lang); var http = new HttpRequest(url, HttpVerb.GET).send(); + httpHandlers.Add(http); + http.operation.completed += ar => { - //TODO check for network errors/timeouts (and find out if operation.completed() is the right place for that) + if (CheckNetworkErrors(http)) + { + return; + } + if (!Directory.Exists(path)) { Directory.CreateDirectory(path); @@ -126,12 +141,69 @@ namespace RothenburgAR.Updater File.WriteAllText(Path.Combine(path, "meta.json"), http.download.text, System.Text.Encoding.UTF8); - //TODO parse json into object and download poi data + var exhibits = JsonConvert.DeserializeObject>(http.download.text); + foreach (var exhibit in exhibits) + { + UpdateMedia(exhibit); + } }; } } + private void UpdateMedia(Exhibit exhibit) + { + //TODO implement feedback: which id is the right one? + // ImageId is apparently just the ExhibitId + // Exhibit doesn't have media, POI does. so the Exhibit.MediaId doesn't make sense + //exhibit.MediaId; + //exhibit.Pois[0].ImageId; + + var mediaIDs = new List { exhibit.MediaId }; + //var mediaIDs = exhibit.Pois.Select(p => p.ImageId).ToList(); + + foreach (var mediaId in mediaIDs) + { + var path = PathHelper.CombinePaths(PathHelper.MediaPath, mediaId); + var url = ApiInfo.FileEndpoint.Replace("{id}", mediaId); + var http = new HttpRequest(url, HttpVerb.GET).send(); + httpHandlers.Add(http); + + http.operation.completed += ar => + { + if (CheckNetworkErrors(http)) + { + return; + } + + if (!Directory.Exists(path)) + { + Directory.CreateDirectory(path); + } + + //TODO find out media type + var type = http.request.GetResponseHeader("Content-Type"); + File.WriteAllBytes(Path.Combine(path, "media.dat"), http.download.data); + }; + } + } + + private bool CheckNetworkErrors(HttpHandler http) + { + if (http.request.isNetworkError || http.request.isHttpError) + { + //TODO notify user about error (decide on level of detail) + Debug.LogError(String.Format("Error while downloading\nurl: {0}\nNetwork Error: {1}\nHttp Error: {2}\nHttp Response Code: {3}", + http.request.url, + http.request.isNetworkError, + http.request.isHttpError, + http.request.responseCode)); + + return true; + } + return false; + } + private void UpdateTracker(ExhibitionVersion exhibition) { throw new NotImplementedException(); @@ -144,8 +216,11 @@ namespace RothenburgAR.Updater void Update() { - + if (httpHandlers.All(h => h.IsDone)) + { + Debug.Log("Done Updating"); + LoadMainScene(); + } } } - } \ No newline at end of file diff --git a/Assets/updaterScene.unity b/Assets/updaterScene.unity index 09af02a..e975ee3 100644 --- a/Assets/updaterScene.unity +++ b/Assets/updaterScene.unity @@ -191,9 +191,9 @@ Camera: m_PrefabParentObject: {fileID: 0} m_PrefabInternal: {fileID: 0} m_GameObject: {fileID: 603935591} - m_Enabled: 1 + m_Enabled: 0 serializedVersion: 2 - m_ClearFlags: 1 + m_ClearFlags: 2 m_BackGroundColor: {r: 0.19215687, g: 0.3019608, b: 0.4745098, a: 0} m_NormalizedViewPortRect: serializedVersion: 2 diff --git a/ProjectSettings/EditorBuildSettings.asset b/ProjectSettings/EditorBuildSettings.asset index a7148ee..b1729a0 100644 --- a/ProjectSettings/EditorBuildSettings.asset +++ b/ProjectSettings/EditorBuildSettings.asset @@ -8,3 +8,6 @@ EditorBuildSettings: - enabled: 1 path: Assets/updaterScene.unity guid: 974eb12c09ab8804392cefb59d4a0de8 + - enabled: 1 + path: Assets/mainScene.unity + guid: 26344e586197d424bb80c37c69080abb