/// <summary> /// Load the settings from a file /// </summary> /// <param name="filename">Name of settings file</param> /// <returns></returns> public static async Task <AppSettings> RestoreAsync(string filename) { try { StorageFile sessionFile = await SettingsFolder.CreateFileAsync(filename, CreationCollisionOption.OpenIfExists); if (sessionFile == null) { return(new AppSettings()); } IInputStream sessionInputStream = await sessionFile.OpenReadAsync(); var serializer = new XmlSerializer(typeof(AppSettings)); AppSettings temp = (AppSettings)serializer.Deserialize(sessionInputStream.AsStreamForRead()); sessionInputStream.Dispose(); return(temp); } catch (Exception ex) { Debug.WriteLine("AppSettings.RestoreAsync(): " + ex.Message); // Log telemetry event about this exception var events = new Dictionary <string, string> { { "AppSettings", ex.Message } }; TelemetryHelper.TrackEvent("FailedToRestoreSettings", events); // If settings.xml file is corrupted and cannot be read - behave as if it does not exist. return(new AppSettings()); } }
/// <summary> /// Attempts to upload the given file, and will recursively retry until the MaxRetries limit is reached. /// </summary> /// <param name="file">The file to upload. Assumes calling method has sole access to the file. Will delete the file after uploading</param> /// <param name="tryNumber">The number of the attempt being made. Should always initially be called with a value of 1</param> /// <returns></returns> private async Task uploadWithRetry(StorageFile file, int tryNumber = 1) { HttpResponseMessage response = await oneDriveConnector.UploadFileAsync(file, String.Format("{0}/{1}", App.Controller.XmlSettings.OneDriveFolderPath, DateTime.Now.ToString("yyyy_MM_dd"))); bool success = await parseResponse(response, tryNumber); var events = new Dictionary <string, string>(); if (success) { numberUploaded++; await file.DeleteAsync(); this.lastUploadTime = DateTime.Now; } else if (tryNumber <= MaxTries) { events.Add("Retrying upload", tryNumber.ToString()); TelemetryHelper.TrackEvent("FailedToUploadPicture - Next Retry Beginning", events); await uploadWithRetry(file, ++tryNumber); } else { events.Add("Max upload attempts reached", tryNumber.ToString()); TelemetryHelper.TrackEvent("FailedToUploadPicture - All Retries failed", events); } }
/******************************************************************************************* * PUBLIC METHODS *******************************************************************************************/ public async Task Initialize() { webcam = new UsbCamera(); try { await webcam.InitializeAsync(); this.isEnabled = true; } catch (Exception ex) { var events = new Dictionary <string, string> { { "UsbCamera", ex.Message } }; TelemetryHelper.TrackEvent("FailedToInitializeMediaCapture", events); } //Initialize PIR Sensor pirSensor = new PirSensor(App.Controller.XmlSettings.GpioMotionPin, PirSensor.SensorType.ActiveLow); pirSensor.motionDetected += PirSensor_MotionDetected; Interlocked.Exchange(ref isCapturing, 0); PhotoTaken = delegate { }; }
public async void DeleteExpiredPictures() { try { List <string> pictures = await listPictures(AppSettings.FolderName); foreach (string picture in pictures) { //Calculate oldest time in ticks using the user selected storage duration long oldestTime = DateTime.UtcNow.Ticks - TimeSpan.FromDays(App.Controller.XmlSettings.StorageDuration).Ticks; //Get the time of image creation in ticks string picName = picture.Split('_')[3]; if (picName.CompareTo(oldestTime.ToString()) < 0) { int index = picture.LastIndexOf(AppSettings.FolderName + "/") + AppSettings.FolderName.Length + 1; await deletePicture(picture.Substring(index)); } } } catch (Exception ex) { Debug.WriteLine("Exception in deleteExpiredPictures() " + ex.Message); // Log telemetry event about this exception var events = new Dictionary <string, string> { { "Azure", ex.Message } }; TelemetryHelper.TrackEvent("FailedToDeletePicture", events); } }
/******************************************************************************************* * PRIVATE METHODS ********************************************************************************************/ private async Task uploadPictureToAzure(string imageName, StorageFile imageFile) { //Log data for upload attempt Windows.Storage.FileProperties.BasicProperties fileProperties = await imageFile.GetBasicPropertiesAsync(); Dictionary <string, string> properties = new Dictionary <string, string> { { "File Size", fileProperties.Size.ToString() } }; TelemetryHelper.TrackEvent("Azure picture upload attempt", properties); try { //Create a blank blob CloudBlockBlob newBlob = blobContainer.GetBlockBlobReference(imageName); //Add image data to blob await newBlob.UploadFromFileAsync(imageFile); } catch (Exception ex) { //This failure will be logged in telemetry in the enclosing UploadPictures function. We don't want this to be recorded twice. throw new Exception("Exception in uploading pictures to Azure: " + ex.Message); } //Log successful upload event TelemetryHelper.TrackEvent("Azure picture upload success", properties); }
public async void UploadPictures() { if (oneDriveConnector.isLoggedIn) { // Stop timer to allow time for uploading pictures in case next timer tick overlaps with this ongoing one AppController.uploadPicturesTimer.Stop(); try { QueryOptions querySubfolders = new QueryOptions(); querySubfolders.FolderDepth = FolderDepth.Deep; StorageFolder cacheFolder = KnownFolders.PicturesLibrary; cacheFolder = await cacheFolder.GetFolderAsync(AppSettings.FolderName); var result = cacheFolder.CreateFileQueryWithOptions(querySubfolders); var files = await result.GetFilesAsync(0, MaxPictureUpload); foreach (StorageFile file in files) { try { await uploadWithRetry(file); } catch (Exception ex) { Debug.WriteLine("UploadPictures(): " + ex.Message); // Log telemetry event about this exception var events = new Dictionary <string, string> { { "OneDrive", ex.Message } }; events.Add("File Failure", "File name: " + file.Name); TelemetryHelper.TrackEvent("FailedToUploadPicture", events); TelemetryHelper.TrackException(ex); } } } catch (Exception ex) { Debug.WriteLine("Exception in UploadPictures() " + ex.Message); // Log telemetry event about this exception var events = new Dictionary <string, string> { { "OneDrive", ex.Message } }; events.Add("Setup routine failure", "Exception thrown getting file list from pictures library"); TelemetryHelper.TrackEvent("FailedToUploadPicture", events); TelemetryHelper.TrackException(ex); } finally { AppController.uploadPicturesTimer.Start(); } } }
public async void UploadPictures() { // Stop timer to allow time for uploading pictures in case next timer tick overlaps with this ongoing one AppController.uploadPicturesTimer.Stop(); try { var querySubfolders = new QueryOptions(); querySubfolders.FolderDepth = FolderDepth.Deep; var cacheFolder = KnownFolders.PicturesLibrary; cacheFolder = await cacheFolder.GetFolderAsync("securitysystem-cameradrop"); var result = cacheFolder.CreateFileQueryWithOptions(querySubfolders); var count = await result.GetItemCountAsync(); var files = await result.GetFilesAsync(); foreach (StorageFile file in files) { //Image name contains creation time string imageName = string.Format(AppSettings.ImageNameFormat, DateTime.Now.ToString("yyyy_MM_dd/HH"), DateTime.UtcNow.Ticks.ToString()); if (file.IsAvailable) { //Upload image to blob storage await uploadPictureToAzure(imageName, file); //Delete image from local storage after a successful upload await file.DeleteAsync(); } } this.lastUploadTime = DateTime.Now; } catch (Exception ex) { Debug.WriteLine("Exception in uploadPictures() " + ex.Message); // Log telemetry event about this exception var events = new Dictionary <string, string> { { "Azure", ex.Message } }; TelemetryHelper.TrackEvent("FailedToUploadPicture", events); } finally { AppController.uploadPicturesTimer.Start(); } }
/// <summary> /// Load the settings from a file /// </summary> /// <param name="filename">Name of settings file</param> /// <returns></returns> public static async Task <AppSettings> RestoreAsync(string filename) { try { await SettingsFolder.GetFileAsync(filename); } catch (FileNotFoundException) { StorageFile securityLogFile = await SettingsFolder.CreateFileAsync(@"settings.xml", CreationCollisionOption.FailIfExists); await FileIO.AppendTextAsync(securityLogFile, "<?xml version=\"1.0\" encoding=\"utf-8\"?>" + Environment.NewLine); await FileIO.AppendTextAsync(securityLogFile, "<AppSettings xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\">" + Environment.NewLine); await FileIO.AppendTextAsync(securityLogFile, "</AppSettings>" + Environment.NewLine); } try { StorageFile sessionFile = await SettingsFolder.CreateFileAsync(filename, CreationCollisionOption.OpenIfExists); if (sessionFile == null) { return(new AppSettings()); } IInputStream sessionInputStream = await sessionFile.OpenReadAsync(); var serializer = new XmlSerializer(typeof(AppSettings)); AppSettings temp = (AppSettings)serializer.Deserialize(sessionInputStream.AsStreamForRead()); sessionInputStream.Dispose(); return(temp); } catch (Exception ex) { Debug.WriteLine("AppSettings.RestoreAsync(): " + ex.Message); // Log telemetry event about this exception var events = new Dictionary <string, string> { { "AppSettings", ex.Message } }; TelemetryHelper.TrackEvent("FailedToRestoreSettings", events); // If settings.xml file is corrupted and cannot be read - behave as if it does not exist. return(new AppSettings()); } }
private void uploadPicturesTimer_Tick(object sender, object e) { try { Storage.UploadPictures(); }catch (Exception ex) { Debug.WriteLine("uploadPicturesTimer_Tick() Exception: " + ex.Message); // Log telemetry event about this exception var events = new Dictionary <string, string> { { "Controller", ex.Message } }; TelemetryHelper.TrackEvent("FailedToDispose", events); } }
/// <summary> /// Parses the GET parameters from the URL and then uses them to log into OneDrive /// </summary> /// <param name="uri"></param> /// <returns></returns> public async Task ParseOneDriveUri(Uri uri) { var oneDrive = App.Controller.Storage as OneDrive; if (oneDrive == null) { return; } try { var decoder = new WwwFormUrlDecoder(uri.Query); foreach (WwwFormUrlDecoderEntry entry in decoder) { // codeUrl is the parameter that contains the URL that was pasted into the textbox on the OneDrive page if (entry.Name.Equals("codeUrl")) { string codeUrl = WebUtility.UrlDecode(entry.Value); var codeUri = new Uri(codeUrl); var codeDecoder = new WwwFormUrlDecoder(codeUri.Query); foreach (WwwFormUrlDecoderEntry subEntry in codeDecoder) { if (subEntry.Name.Equals("code")) { await oneDrive.Authorize(subEntry.Value); break; } } break; } else if (entry.Name.Equals("logout")) { await oneDrive.Logout(); } } } catch (Exception ex) { // Log telemetry event about this exception var events = new Dictionary <string, string> { { "WebHelper", ex.Message } }; TelemetryHelper.TrackEvent("FailedToParseOneDriveUri", events); } }
public async void DeleteExpiredPictures() { try { string folder = string.Format(AppSettings.ImageNameFormat, App.Controller.XmlSettings.OneDriveFolderPath, DateTime.Now.Subtract(TimeSpan.FromDays(App.Controller.XmlSettings.StorageDuration)).ToString("yyyy_MM_dd")); //List pictures in old day folder KeyValuePair <HttpResponseMessage, IList <string> > responseItems = await oneDriveConnector.ListFilesAsync(folder); List <string> pictures = new List <string>(responseItems.Value); if (pictures != null) { //Delete all pictures from the day foreach (string picture in pictures) { try { await deleteWithRetry(picture, folder); } catch (Exception ex) { Debug.WriteLine("Exception in deleteExpiredPictures() " + ex.Message); // Log telemetry event about this exception var events = new Dictionary <string, string> { { "OneDrive", ex.Message } }; events.Add("File Failure", "File name: " + picture); TelemetryHelper.TrackEvent("FailedToDeletePicture", events); TelemetryHelper.TrackException(ex); } } } } catch (Exception ex) { Debug.WriteLine("Exception in deleteExpiredPictures() " + ex.Message); // Log telemetry event about this exception var events = new Dictionary <string, string> { { "OneDrive", ex.Message } }; events.Add("Setup routine failure", "Exception thrown getting file list from OneDrive"); TelemetryHelper.TrackEvent("FailedToDeletePicture", events); TelemetryHelper.TrackException(ex); } }
/// <summary> /// Invoked when application execution is being suspended. Application state is saved /// without knowing whether the application will be terminated or resumed with the contents /// of memory still intact. /// </summary> /// <param name="sender">The source of the suspend request.</param> /// <param name="e">Details about the suspend request.</param> private void OnSuspending(object sender, SuspendingEventArgs e) { // Track App suspension/exit: GlobalStopwatch.Stop(); TelemetryHelper.TrackMetric("AppRuntime", GlobalStopwatch.Elapsed.TotalMilliseconds); var metrics = new Dictionary <string, string> { { "appRuntime", GlobalStopwatch.Elapsed.TotalMilliseconds.ToString() } }; TelemetryHelper.TrackEvent("UserRuntime", metrics); var deferral = e.SuspendingOperation.GetDeferral(); //TODO: Save application state and stop any background activity deferral.Complete(); }
/// <summary> /// Parses the GET parameters from the URL and loads them into the settings /// </summary> /// <param name="uri"></param> public void ParseUriIntoSettings(Uri uri) { var decoder = new WwwFormUrlDecoder(uri.Query); // Take the parameters from the URL and put it into Settings foreach (WwwFormUrlDecoderEntry entry in decoder) { try { var field = typeof(AppSettings).GetField(entry.Name); if (field.FieldType == typeof(int)) { field.SetValue(App.Controller.XmlSettings, Convert.ToInt32(entry.Value)); } else if (field.FieldType == typeof(CameraType) || field.FieldType == typeof(StorageProvider)) { field.SetValue(App.Controller.XmlSettings, Enum.Parse(field.FieldType, entry.Value)); } else { //if the field being saved is the alias, and the alias has changed, send a telemetry event if (0 == field.Name.CompareTo("MicrosoftAlias") && 0 != entry.Value.CompareTo(App.Controller.XmlSettings.MicrosoftAlias)) { Dictionary <string, string> properties = new Dictionary <string, string> { { "Alias", entry.Value } }; TelemetryHelper.TrackEvent("Alias Changed", properties); } field.SetValue(App.Controller.XmlSettings, entry.Value); } } catch (Exception ex) { Debug.WriteLine(ex.Message); // Log telemetry event about this exception var events = new Dictionary <string, string> { { "WebHelper", ex.Message } }; TelemetryHelper.TrackEvent("FailedToParseUriIntoSettings", events); } } }
/// <summary> /// Invoked when the application is launched normally by the end user. Other entry points /// will be used such as when the application is launched to open a specific file. /// </summary> /// <param name="e">Details about the launch request and process.</param> protected async override void OnLaunched(LaunchActivatedEventArgs e) { GlobalStopwatch.Start(); await Controller.Initialize(); TelemetryHelper.TrackEvent("Application Launched"); #if DEBUG if (System.Diagnostics.Debugger.IsAttached) { this.DebugSettings.EnableFrameRateCounter = true; } #endif Frame rootFrame = Window.Current.Content as Frame; // Do not repeat app initialization when the Window already has content, // just ensure that the window is active if (rootFrame == null) { // Create a Frame to act as the navigation context and navigate to the first page rootFrame = new Frame(); rootFrame.NavigationFailed += OnNavigationFailed; if (e.PreviousExecutionState == ApplicationExecutionState.Terminated) { //TODO: Load state from previously suspended application } // Place the frame in the current Window Window.Current.Content = rootFrame; } if (rootFrame.Content == null) { // When the navigation stack isn't restored navigate to the first page, // configuring the new page by passing required information as a navigation // parameter rootFrame.Navigate(typeof(MainPage), e.Arguments); } // Ensure the current window is active Window.Current.Activate(); }
/// <summary> /// Parses the HTTP response from a call one OneDrive, and sends telemetry about the response /// </summary> /// <param name="response">The HTTP response message from the OneDrive call</param> /// <param name="tryNumber">The attempt number of the call (first call is 1, etc)</param> /// <returns>Whether or not the reponse status from the server indicated success</returns> private async Task <bool> parseResponse(HttpResponseMessage response, int tryNumber) { bool successStatus; var events = new Dictionary <string, string>(); events.Add("Attempt number", tryNumber.ToString()); if (response.IsSuccessStatusCode) { successStatus = true; TelemetryHelper.TrackEvent("HttpSuccess", events); } else { successStatus = false; events.Add(response.StatusCode.ToString(), response.ReasonPhrase); if (response.StatusCode == HttpStatusCode.Unauthorized) { events.Add("Recovery Attempt", "AuthorizeWithRefreshToken()"); if (App.Controller.XmlSettings.OneDriveRefreshToken == "") { events.Add("App.Controller.XmlSettings.OneDriveRefreshToken", "Invalid Empty String"); } else { events.Add("App.Controller.XmlSettings.OneDriveRefreshToken", "Valid String, attempting reauth"); await oneDriveConnector.Reauthorize(); } TelemetryHelper.TrackEvent("HttpErrorOnRequest", events); } else if ((500 <= (int)response.StatusCode) && ((int)response.StatusCode < 600)) { events.Add("Recovery attempt", "Server side error, automatically attempting again"); TelemetryHelper.TrackEvent("HttpErrorOnRequest", events); } else { events.Add("Recovery Attempt", "Unexpected HTTP response from server, error thrown"); TelemetryHelper.TrackEvent("HttpErrorOnRequest", events); throw new System.Net.Http.HttpRequestException("UnexpectedHttpRequestError"); } } return(successStatus); }
/// <summary> /// Writes a file to the stream /// </summary> /// <param name="file"></param> /// <param name="os"></param> /// <returns></returns> public static async Task WriteFileToStream(StorageFile file, IOutputStream os) { using (Stream resp = os.AsStreamForWrite()) { bool exists = true; try { using (Stream fs = await file.OpenStreamForReadAsync()) { string header = String.Format("HTTP/1.1 200 OK\r\n" + "Content-Length: {0}\r\n" + "Connection: close\r\n\r\n", fs.Length); byte[] headerArray = Encoding.UTF8.GetBytes(header); await resp.WriteAsync(headerArray, 0, headerArray.Length); await fs.CopyToAsync(resp); } } catch (FileNotFoundException ex) { exists = false; // Log telemetry event about this exception var events = new Dictionary <string, string> { { "WebHelper", ex.Message } }; TelemetryHelper.TrackEvent("FailedToWriteFileToStream", events); } if (!exists) { byte[] headerArray = Encoding.UTF8.GetBytes( "HTTP/1.1 404 Not Found\r\n" + "Content-Length:0\r\n" + "Connection: close\r\n\r\n"); await resp.WriteAsync(headerArray, 0, headerArray.Length); } await resp.FlushAsync(); } }
/// <summary> /// Disposes the file upload and deletion timers, camera, and storage /// </summary> public void Dispose() { try { uploadPicturesTimer?.Stop(); deletePicturesTimer?.Stop(); Camera?.Dispose(); Storage?.Dispose(); } catch (Exception ex) { Debug.WriteLine("Controller.Dispose(): " + ex.Message); // Log telemetry event about this exception var events = new Dictionary <string, string> { { "Controller", ex.Message } }; TelemetryHelper.TrackEvent("FailedToDispose", events); } IsInitialized = false; }
public async void DeleteExpiredPictures() { //Delete older images try { var querySubfolders = new QueryOptions(); querySubfolders.FolderDepth = FolderDepth.Deep; var cacheFolder = KnownFolders.PicturesLibrary; cacheFolder = await cacheFolder.GetFolderAsync(AppSettings.FolderName); var result = cacheFolder.CreateFileQueryWithOptions(querySubfolders); var files = await result.GetFilesAsync(); foreach (StorageFile file in files) { //Caluclate oldest time in ticks using the user selected storage duration long oldestTime = DateTime.UtcNow.Ticks - TimeSpan.FromDays(App.Controller.XmlSettings.StorageDuration).Ticks; long picCreated = file.DateCreated.Ticks; if (picCreated < oldestTime) { await file.DeleteAsync(); } } } catch (Exception ex) { Debug.WriteLine("Exception in deleteExpiredPictures() " + ex.Message); // Log telemetry event about this exception var events = new Dictionary <string, string> { { "LocalStorage", ex.Message } }; TelemetryHelper.TrackEvent("FailedToDeletePicture", events); } }
/// <summary> /// Attempts to delete the given picture from the given folder, and will recursively retry until the MaxRetries limit is reached. /// </summary> /// <param name="picture">The name of the picture to delete</param> /// <param name="folder">The name and path of the folder from which to delete the picture</param> /// <param name="tryNumber">The number of the attempt being made. Should always initially be called with a value of 1</param> /// <returns></returns> private async Task deleteWithRetry(string picture, string folder, int tryNumber = 1) { HttpResponseMessage response = await oneDriveConnector.DeleteFileAsync(picture, folder); bool success = await parseResponse(response, tryNumber); var events = new Dictionary <string, string>(); if (success) { //no additional action needed } else if (tryNumber <= MaxTries) { events.Add("Retrying delete", tryNumber.ToString()); TelemetryHelper.TrackEvent("FailedToDeletePicture - Next Retry Beginning", events); await deleteWithRetry(picture, folder, ++tryNumber); } else { events.Add("Max delete attempts reached", tryNumber.ToString()); TelemetryHelper.TrackEvent("FailedToDeletePicture - All Retries failed", events); } }
private async Task writeResponseAsync(string request, IOutputStream os, StreamSocketInformation socketInfo) { try { string[] requestParts = request.Split('/'); #region Request for the root page, so redirect to home page if (request.Equals("/")) { await redirectToPage(NavConstants.HOME_PAGE, os); } #endregion #region Request for the home page else if (request.Contains(NavConstants.HOME_PAGE)) { // Generate the default config page string html = await helper.GenerateStatusPage(); await WebHelper.WriteToStream(html, os); } #endregion #region Request for the settings page else if (request.Contains(NavConstants.SETTINGS_PAGE)) { // Process the GET parameters if (request.Contains("?")) { // Format the URI with the get parameters Uri uri = new Uri("http://1.2.3.4:8000" + request); // Take the parameters from the URL and put it into Settings helper.ParseUriIntoSettings(uri); await AppSettings.SaveAsync(App.Controller.XmlSettings, "Settings.xml"); // This is an event that lets us know what the controller is done restarting after the settings are applied AutoResetEvent ase = new AutoResetEvent(false); // Dispose and Initialize need to be called on UI thread because of DispatcherTimers await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, async() => { try { // Restart the controller to apply new settings App.Controller.Dispose(); await App.Controller.Initialize(); // Create the settings page and add a confirmation message that the settings were applied successfully string html = helper.GeneratePage("Security System Config", "Security System Config", helper.CreateHtmlFormFromSettings(), "<span style='color:Green'>Configuration saved!</span><br><br>"); await WebHelper.WriteToStream(html, os); } catch (Exception ex) { Debug.WriteLine("Error restarting controller: " + ex.Message); } // Signal that the restart is done ase.Set(); }); // Wait for controller restart to finish ase.WaitOne(); } else { // Generate the default config page string html = helper.GeneratePage("Security System Config", "Security System Config", helper.CreateHtmlFormFromSettings()); await WebHelper.WriteToStream(html, os); } } #endregion #region Request for the OneDrive page else if (request.Contains(NavConstants.ONEDRIVE_PAGE)) { // Take in the parameters and try to login to OneDrive if (request.Contains("?")) { // I just put some arbitrary IP and port just so I have a correctly formatted URI, it's not important to have an actual IP + port Uri uri = new Uri("http://1.2.3.4:8000" + request); await helper.ParseOneDriveUri(uri); var oneDrive = App.Controller.Storage as OneDrive; if (oneDrive != null) { if (oneDrive.IsLoggedIn()) { // Save tokens to settings file if we successfully logged in await AppSettings.SaveAsync(App.Controller.XmlSettings, "Settings.xml"); } } } // Generate page and write to stream string html = helper.GenerateOneDrivePage(); await WebHelper.WriteToStream(html, os); } #endregion #region Request for gallery page else if (request.Contains(NavConstants.GALLERY_PAGE)) { string html = ""; var storageType = App.Controller.Storage.GetType(); // If the storage type is OneDrive, generate page with link to OneDrive if (storageType == typeof(OneDrive)) { html = helper.GeneratePage("Gallery", "Gallery", "<b>" + storageType.Name + "</b> is set as your storage provider. " + "Please view your pictures on <a href='http://www.onedrive.com' target='_blank'>OneDrive</a>.<br><br>" + "To view your pictures here, please select <b>" + StorageProvider.Local + "</b> as your storage provider."); } // Otherwise show the gallery for the files on the device else { StorageFolder folder = KnownFolders.PicturesLibrary; int page = 1; int pageSize = 30; // Parse GET parameters if (request.Contains("?")) { Uri uri = new Uri("http://1.2.3.4:8000" + request); var parameters = helper.ParseGetParametersFromUrl(uri); try { // Find the folder that's specified in the parameters folder = await StorageFolder.GetFolderFromPathAsync(parameters["folder"]); if (parameters.ContainsKey("page")) { try { page = Convert.ToInt32(parameters["page"]); } catch (Exception) { } } if (parameters.ContainsKey("pageSize")) { try { pageSize = Convert.ToInt32(parameters["pageSize"]); } catch (Exception) { } } } catch (Exception ex) { Debug.WriteLine("Exception finding folder: " + ex.Message); folder = await folder.GetFolderAsync(AppSettings.FolderName); // Log telemetry event about this exception var events = new Dictionary <string, string> { { "WebServer", ex.Message } }; TelemetryHelper.TrackEvent("FailedToGetFolderFromPath", events); } } else { folder = await folder.GetFolderAsync(AppSettings.FolderName); } // Generate gallery page and write to stream string galleryHtml = await helper.GenerateGallery(folder, page, pageSize); html = helper.GeneratePage("Gallery", "Gallery", galleryHtml); } await WebHelper.WriteToStream(html, os); } #endregion #region Request for API else if (request.Contains("api")) { try { if (requestParts.Length > 2) { switch (requestParts[2].ToLower()) { // An image from the gallery was requested case "gallery": var temp = request.Split(new string[] { "gallery/" }, StringSplitOptions.None); // HTML decode the file path string decodedPath = WebUtility.UrlDecode(temp[1]); // Retrieve the file StorageFile file = await StorageFile.GetFileFromPathAsync(decodedPath); // Write the file to the stream await WebHelper.WriteFileToStream(file, os); break; } } }catch (Exception ex) { Debug.WriteLine("Exception in web API: " + ex.Message); // Log telemetry event about this exception var events = new Dictionary <string, string> { { "WebServer", ex.Message } }; TelemetryHelper.TrackEvent("FailedToProcessApiRequest", events); } } // Request for a file that is in the Assets\Web folder (e.g. logo, css file) #endregion #region Generate the Action page else if (request.Contains(NavConstants.ACTION_PAGE)) { Debug.WriteLine("Action page requested."); //await redirectToPage(NavConstants.HOME_PAGE, os); string html; string result = String.Empty; // Process the GET parameters if (request.Contains("?")) { // Format the URI with the get parameters Uri uri = new Uri("http://1.2.3.4:8000" + request); Dictionary <string, string> parameters = helper.ParseGetParametersFromUrl(uri); foreach (string key in parameters.Keys) { Debug.WriteLine("{0} = {1}", key, parameters[key]); } switch (parameters["myaction"]) { case "takephoto": Debug.WriteLine("Manually Taking photo..."); await App.Controller.Camera.TriggerCapture(); Debug.WriteLine("Photo capture done."); html = helper.GeneratePage("Actions", "Manual actions", helper.GenerationActionPage(), result = "<span style='color:Green'>Photo taken.</span><br><br>"); //await WebHelper.WriteToStream(html, os); break; case "sendknownimages": Debug.WriteLine("Registgering known images with Cortana FaceAPI....."); if (App.Controller.FaceClient == null) { result = "<span style='color:Red'>The FaceAPI key has not been set or is incorrect. Go to the Settings page and review the setting.</span><br><br>"; } else { //await App.Controller.FaceClient.RegisterKnownUsersAsync(); //result = "<span style='color:Green'>Known image upload complete</span><br><br>"; } break; default: break; } } html = helper.GeneratePage("Actions", "Manual actions", helper.GenerationActionPage(), result); await WebHelper.WriteToStream(html, os); } #endregion #region Return assets from web folder or error is nothing else matches else { using (Stream resp = os.AsStreamForWrite()) { bool exists = true; try { var folder = Windows.ApplicationModel.Package.Current.InstalledLocation; // Map the requested path to Assets\Web folder string filePath = @"Assets\Web" + request.Replace('/', '\\'); // Open the file and write it to the stream using (Stream fs = await folder.OpenStreamForReadAsync(filePath)) { string header = String.Format("HTTP/1.1 200 OK\r\n" + "Content-Length: {0}\r\n{1}" + "Connection: close\r\n\r\n", fs.Length, ((request.Contains("css")) ? "Content-Type: text/css\r\n" : "")); byte[] headerArray = Encoding.UTF8.GetBytes(header); await resp.WriteAsync(headerArray, 0, headerArray.Length); await fs.CopyToAsync(resp); } } catch (FileNotFoundException ex) { exists = false; // Log telemetry event about this exception var events = new Dictionary <string, string> { { "WebServer", ex.Message } }; TelemetryHelper.TrackEvent("FailedToOpenStream", events); } // Send 404 not found if can't find file if (!exists) { byte[] headerArray = Encoding.UTF8.GetBytes( "HTTP/1.1 404 Not Found\r\n" + "Content-Length:0\r\n" + "Connection: close\r\n\r\n"); await resp.WriteAsync(headerArray, 0, headerArray.Length); } await resp.FlushAsync(); } } #endregion } catch (FaceAPIException fex) { #region Track error for debugging Debug.WriteLine("Exception in FaceAPI code: " + fex.Message); #endregion #region Display error to user try { // Try to send an error page back if there was a problem servicing the request string html = helper.GeneratePage("Error", "Error", "There's been an error: " + fex.Message + "<br><br>"); await WebHelper.WriteToStream(html, os); } catch (Exception e) { TelemetryHelper.TrackException(e); } #endregion } catch (Exception ex) { #region Track error for debugging Debug.WriteLine("Exception in writeResponseAsync(): " + ex.Message); Debug.WriteLine(ex.StackTrace); // Log telemetry event about this exception //var events = new Dictionary<string, string> { { "WebServer", ex.Message } }; //TelemetryHelper.TrackEvent("FailedToWriteResponse", events); #endregion #region Display error to user try { // Try to send an error page back if there was a problem servicing the request string html = helper.GeneratePage("Error", "Error", "There's been an error: " + ex.Message + "<br><br>" + ex.StackTrace); await WebHelper.WriteToStream(html, os); } catch (Exception e) { TelemetryHelper.TrackException(e); } #endregion } }
/// <summary> /// Initializes the controller: Loads settings, starts web server, sets up the camera and storage providers, /// tries to log into OneDrive (if OneDrive is selected), and starts the file upload and deletion timers /// </summary> /// <returns></returns> public async Task Initialize() { try { // Load settings from file XmlSettings = await AppSettings.RestoreAsync("Settings.xml"); // Create securitysystem-cameradrop sub folder if it doesn't exist StorageFolder folder = KnownFolders.PicturesLibrary; if (await folder.TryGetItemAsync(AppSettings.FolderName) == null) { await folder.CreateFolderAsync(AppSettings.FolderName); } // Start web server on port 8000 if (!Server.IsRunning) { Server.Start(8000); } Camera = CameraFactory.Get(XmlSettings.CameraType); Storage = StorageFactory.Get(XmlSettings.StorageProvider); await Camera.Initialize(); // Try to log into OneDrive using existing Access Token in settings file if (Storage.GetType() == typeof(OneDrive)) { var oneDrive = App.Controller.Storage as OneDrive; if (oneDrive != null) { if (!oneDrive.IsLoggedIn()) { try { await oneDrive.AuthorizeWithRefreshToken(XmlSettings.OneDriveRefreshToken); } catch (Exception ex) { Debug.WriteLine(ex.Message); // Log telemetry event about this exception var events = new Dictionary <string, string> { { "Controller", ex.Message } }; TelemetryHelper.TrackEvent("FailedToLoginOneDrive", events); } } } } this.alljoynManager = new AllJoynManager(); await this.alljoynManager.Initialize(this.Camera, this.Storage); //Timer controlling camera pictures with motion uploadPicturesTimer = new DispatcherTimer(); uploadPicturesTimer.Interval = TimeSpan.FromSeconds(uploadInterval); uploadPicturesTimer.Tick += uploadPicturesTimer_Tick; uploadPicturesTimer.Start(); //Timer controlling deletion of old pictures deletePicturesTimer = new DispatcherTimer(); deletePicturesTimer.Interval = TimeSpan.FromHours(deleteInterval); deletePicturesTimer.Tick += deletePicturesTimer_Tick; deletePicturesTimer.Start(); IsInitialized = true; } catch (Exception ex) { Debug.WriteLine("Controller.Initialize() Error: " + ex.Message); // Log telemetry event about this exception var events = new Dictionary <string, string> { { "Controller", ex.Message } }; TelemetryHelper.TrackEvent("FailedToInitialize", events); } }