예제 #1
0
        /// <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());
            }
        }
예제 #2
0
        /// <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);
            }
        }
예제 #3
0
        /*******************************************************************************************
        * 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 { };
        }
예제 #4
0
        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);
            }
        }
예제 #5
0
        /*******************************************************************************************
         * 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);
        }
예제 #6
0
        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();
                }
            }
        }
예제 #7
0
        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();
            }
        }
예제 #8
0
        /// <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());
            }
        }
예제 #9
0
        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);
            }
        }
예제 #10
0
        /// <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);
            }
        }
예제 #11
0
        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);
            }
        }
예제 #12
0
        /// <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();
        }
예제 #13
0
        /// <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);
                }
            }
        }
예제 #14
0
        /// <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();
        }
예제 #15
0
        /// <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);
        }
예제 #16
0
        /// <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();
            }
        }
예제 #17
0
        /// <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;
        }
예제 #18
0
        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);
            }
        }
예제 #19
0
        /// <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);
            }
        }
예제 #20
0
        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.&nbsp;&nbsp;"
                                                   + "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
            }
        }
예제 #21
0
        /// <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);
            }
        }