Beispiel #1
0
 /// <summary>
 /// Initiates lists used
 /// </summary>
 void SetupLists()
 {
     HeartDebugHandler.debugLog("Setting up Lists");
     hdata_Beat  = new Queue <HeartDataPoint>();
     hdata_Rate  = new Queue <HeartDataPoint>();
     hdata_Steps = new Queue <HeartDataPoint>();
 }
Beispiel #2
0
        /// <summary>
        /// onResume reconnects if app isn't already connected or currently connecting
        /// </summary>
        protected override async void OnResume()
        {
            base.OnResume();
            HeartDebugHandler.debugLog("OnResume ran");


            await WearableClass.DataApi.RemoveListenerAsync(mGoogleApiClient, this);

            await WearableClass.DataApi.AddListener(mGoogleApiClient, this);

            await WearableClass.MessageApi.RemoveListenerAsync(mGoogleApiClient, this);

            await WearableClass.MessageApi.AddListener(mGoogleApiClient, this);

            await WearableClass.NodeApi.RemoveListenerAsync(mGoogleApiClient, this);

            await WearableClass.NodeApi.AddListener(mGoogleApiClient, this);

            if (!mGoogleApiClient.IsConnected && !mGoogleApiClient.IsConnecting)
            {
                //updateConnectionStatusString("Connecting");
                connectionStatusHandler.updateStatus("Connecting");
                mGoogleApiClient.Connect();
            }
        }
Beispiel #3
0
        /// <summary>
        /// Initiates the activity
        /// </summary>
        /// <param name="savedInstanceState"></param>
        protected override void OnCreate(Bundle savedInstanceState)
        {
            base.OnCreate(savedInstanceState);

            SetContentView(Resource.Layout.settings_activity);
            HeartDebugHandler.debugLog("Settings Launched");
            // Create your application here
        }
Beispiel #4
0
 protected override void OnActivityResult(int requestCode, Result resultCode, Intent data)
 {
     HeartDebugHandler.debugLog("Activity results are in!");
     if (resultCode == Result.Ok)
     {
         Bundle extras = data.Extras;
     }
 }
Beispiel #5
0
 public void OnPeerDisconnected(INode peer)
 {
     HeartDebugHandler.debugLog("OnPeerDisconnected: " + peer);
     handler.Post(() => {
         //updateConnectionStatusString("Peer Disconnected");
         connectionStatusHandler.updateStatus("Peer Disconnected");
     });
 }
Beispiel #6
0
        public void onSettingsButtonClicked(View view)
        {
            HeartDebugHandler.debugLog("Settings clicked!");
            Intent intent = new Intent(this, typeof(SettingsActivity));

            StartActivity(intent);
            HeartDebugHandler.debugLog("BreakPoint");
        }
Beispiel #7
0
        /// <summary>
        /// Legacy, ported to new status string handler
        /// </summary>
        /// <param name="text"></param>
        //private void updateConnectionStatusString(string text)
        //{
        //    RunOnUiThread(() =>
        //    {
        //        //connectionStatusTextView.Text = text;
        //        connectionStatusHandler.updateStatus(text);
        //    });
        //}

        /// <summary>
        /// Legacy, ported to new status string handler
        /// </summary>
        /// <param name="text"></param>
        //private void updateStatusString(string text)
        //{
        //    RunOnUiThread(() =>
        //    {
        //        //statusTextView.Text = text;
        //        dataStatusHandler.updateStatus(text);
        //    });
        //}


        /// <summary>
        /// finds UI components and assigns them to variables
        /// </summary>
        void SetupViews()
        {
            HeartDebugHandler.debugLog("Setting up views");
            startActivityBtn         = FindViewById(Resource.Id.start_wearable_activity);
            statusTextView           = (TextView)FindViewById(Resource.Id.statusText);
            connectionStatusTextView = (TextView)FindViewById(Resource.Id.connectionStatusText);
            chartView = (Microcharts.Droid.ChartView)FindViewById(Resource.Id.linechart);
            imageView = (ImageView)FindViewById(Resource.Id.statusImage);
        }
        /// <summary>
        /// takes a filename, and if that file exists, it gets deleted.
        /// </summary>
        /// <param name="filename"></param>
        private static void DeleteDataFile(string filename)
        {
            string fileString = System.IO.Path.Combine(System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal), filename);

            Java.IO.File file = new Java.IO.File(fileString);
            if (file.Exists())
            {
                HeartDebugHandler.debugLog("File exists, deleting");
                file.Delete();
            }
        }
Beispiel #9
0
        /// <summary>
        /// Main method sort of speak
        /// </summary>
        /// <param name="bundle"></param>
        protected override void OnCreate(Bundle bundle)
        {
            base.OnCreate(bundle);
            handler = new Handler();
            HeartDebugHandler.debugLog("OnCreate");
            connectionAttempts = 0;
            SetContentView(Resource.Layout.main_activity);
            HeartDebugHandler.debugLog("App Launched");
            SetupViews();
            SetupLists();

            //gridViewContainer

            //gridView = FindViewById<ListView>(Resource.Id.gridViewContainer);
            swipeRefreshLayout = FindViewById <SwipeRefreshLayout>(Resource.Id.swipeRefreshLayout);

            // Elevation helps users understand the relative importance of each element and focus their attention to the task at hand. (Optional)
            // swipeRefreshLayout.Elevation = 10;

            swipeRefreshLayout.Refresh += delegate(object sender, System.EventArgs e)
            {
                swipeRefreshLayout.Refreshing = true;

                Toast.MakeText(this, "Reconnecting", ToastLength.Short).Show();
                if (!mGoogleApiClient.IsConnected && !mGoogleApiClient.IsConnecting)
                {
                    //updateConnectionStatusString("Connecting");
                    connectionStatusHandler.updateStatus("Connecting");
                    mGoogleApiClient.Connect();
                }


                swipeRefreshLayout.Refreshing = false;
            };

            dataStatusHandler       = new StatusHandler(statusTextView, "No data received");
            connectionStatusHandler = new StatusHandler(connectionStatusTextView, "");

            mGoogleApiClient = new GoogleApiClient.Builder(this)
                               .AddApi(WearableClass.API)
                               .AddConnectionCallbacks(this)
                               .AddOnConnectionFailedListener(this)
                               .Build();


            if (!mGoogleApiClient.IsConnected && !mGoogleApiClient.IsConnecting)
            {
                connectionStatusHandler.updateStatus("Connecting");
                mGoogleApiClient.Connect();
            }
        }
Beispiel #10
0
        /// <summary>
        /// Disconnects the wearable connection, and removes listeners
        /// </summary>
        protected override async void OnPause()
        {
            base.OnPause();
            HeartDebugHandler.debugLog("App Paused");
            //if (!mResolvingError) { }

            //updateConnectionStatusString("Disconnecting");
            connectionStatusHandler.updateStatus("Disconnecting");
            //TODO: should probably look into which listeners are actually needed, I believe it's only the dataApi and maybe the NodeApi that are actually in use
            await WearableClass.DataApi.RemoveListenerAsync(mGoogleApiClient, this);

            await WearableClass.MessageApi.RemoveListenerAsync(mGoogleApiClient, this);

            await WearableClass.NodeApi.RemoveListenerAsync(mGoogleApiClient, this);

            mGoogleApiClient.Disconnect();
        }
Beispiel #11
0
        /// <summary>
        /// Removes listeners and disconnects from the wearable
        /// </summary>
        protected override async void OnStop()
        {
            base.OnStop();
            HeartDebugHandler.debugLog("App Stopped");
            //if (!mResolvingError)
            //{
            await WearableClass.DataApi.RemoveListenerAsync(mGoogleApiClient, this);

            await WearableClass.MessageApi.RemoveListenerAsync(mGoogleApiClient, this);

            await WearableClass.NodeApi.RemoveListenerAsync(mGoogleApiClient, this);

            mGoogleApiClient.Disconnect();
            //updateConnectionStatusString("Disconnecting");
            connectionStatusHandler.updateStatus("Disconnecting");
            //}
        }
Beispiel #12
0
 /// <summary>
 /// Notifies user that connection was failed, although it tries connecting up to 10 times(defined variable up top)
 /// </summary>
 /// <param name="result"></param>
 public async void OnConnectionFailed(Android.Gms.Common.ConnectionResult result)
 {
     HeartDebugHandler.debugLog("Connection failed");
     connectionAttempts++;
     if (connectionAttempts < maxConnectionAttempts)
     {
         if (!mGoogleApiClient.IsConnected && !mGoogleApiClient.IsConnecting)
         {
             mGoogleApiClient.Connect();
             //updateConnectionStatusString("Connecting");
             connectionStatusHandler.updateStatus("Connecting");
         }
     }
     else
     {
         //updateConnectionStatusString("Connection failed");
         connectionStatusHandler.updateStatus("Connection failed");
     }
 }
Beispiel #13
0
        //TODO: Clean up the whole connections and listeners mess, debug and find out when each is called and connect/add listeners where appropriate

        /// <summary>
        /// When connected it adds the listeners again
        /// </summary>
        /// <param name="connectionHint"></param>
        public async void OnConnected(Bundle connectionHint)
        {
            HeartDebugHandler.debugLog("Google API CLient was connected");
            //mResolvingError = false;
            connectionAttempts       = 0;
            startActivityBtn.Enabled = true;
            await WearableClass.DataApi.RemoveListenerAsync(mGoogleApiClient, this);

            await WearableClass.DataApi.AddListener(mGoogleApiClient, this);

            await WearableClass.MessageApi.RemoveListenerAsync(mGoogleApiClient, this);

            await WearableClass.MessageApi.AddListener(mGoogleApiClient, this);

            await WearableClass.NodeApi.RemoveListenerAsync(mGoogleApiClient, this);

            await WearableClass.NodeApi.AddListener(mGoogleApiClient, this);

            //updateConnectionStatusString("Connected");
            connectionStatusHandler.updateStatus("Connected");
        }
Beispiel #14
0
        /// <summary>
        /// On start, reconnects to the wearable if it's not already connected
        /// </summary>
        protected override async void OnStart()
        {
            base.OnStart();
            HeartDebugHandler.debugLog("OnStart ran");
            //Removes listeners first, then adds them; haven't found a good way to check if there is a listener currently
            await WearableClass.DataApi.RemoveListenerAsync(mGoogleApiClient, this);

            await WearableClass.DataApi.AddListener(mGoogleApiClient, this);

            await WearableClass.MessageApi.RemoveListenerAsync(mGoogleApiClient, this);

            await WearableClass.MessageApi.AddListener(mGoogleApiClient, this);

            await WearableClass.NodeApi.RemoveListenerAsync(mGoogleApiClient, this);

            await WearableClass.NodeApi.AddListener(mGoogleApiClient, this);

            if (!mGoogleApiClient.IsConnected && !mGoogleApiClient.IsConnecting)
            {
                //updateConnectionStatusString("Connecting");
                connectionStatusHandler.updateStatus("Connecting");
                mGoogleApiClient.Connect();
            }
        }
Beispiel #15
0
        public async void onUploadAllClicked(View view)
        {
            TextView codeView = FindViewById <TextView>(Resource.Id.mainCodeTV);

            codeView.Visibility = ViewStates.Invisible;

            HeartDebugHandler.debugLog("Getting json string");
            string jsonStringSteps = await HeartFileHandler.getJSONString(HeartFileHandler.FILENAME_STEPS);

            string jsonStringRate = await HeartFileHandler.getJSONString(HeartFileHandler.FILENAME_HEARTRATE);

            string jsonStringBeat = await HeartFileHandler.getJSONString(HeartFileHandler.FILENAME_HEARTBEAT);

            //HeartDebugHandler.debugLog(jsonString.Substring(jsonString.Length-30));
            //HeartDebugHandler.debugLog("String got, length: " + jsonString.Length);

            HeartDebugHandler.debugLog("Sending data");

            //HeartNetworkHandler.sendPostRequest(this, jsonString, codeView);
            //HeartNetworkHandler.sendPostRequest(this, jsonStringSteps, jsonStringRate, jsonStringBeat, codeView);
            HeartPostSender hps = new HeartPostSender(this, codeView, jsonStringSteps, jsonStringRate, jsonStringBeat);

            hps.SendData();
        }
Beispiel #16
0
        public void onSaveToFileClicked(View view)
        {
            HeartDebugHandler.debugLog("Save to file clicked");

            if (hdata_Steps.Count > 0)
            {
                HeartFileHandler.saveData(hdata_Steps, HeartFileHandler.FILENAME_STEPS, dataStatusHandler);
            }

            if (hdata_Rate.Count > 0)
            {
                HeartFileHandler.saveData(hdata_Rate, HeartFileHandler.FILENAME_HEARTRATE, dataStatusHandler);
            }

            if (hdata_Beat.Count > 0)
            {
                HeartFileHandler.saveData(hdata_Beat, HeartFileHandler.FILENAME_HEARTBEAT, dataStatusHandler);
            }

            if (hdata_Steps.Count == 0 && hdata_Beat.Count == 0 && hdata_Rate.Count == 0)
            {
                dataStatusHandler.updateStatus("No unsaved data");
            }
        }
        /// <summary>
        /// The main task for writing the data to file; it get's the full set of data going in to the file,
        /// it then deletes the current file(if it exists) and creates a new file containing the incoming data, it then updates the status(TextView) of the app
        /// </summary>
        /// <param name="dataPoints"></param>
        /// <param name="fileName"></param>
        /// <param name="dataStatusHandler"></param>
        /// <returns></returns>
        private static async Task storeDataPointsTask(List <HeartDataPoint> dataPoints, string fileName, StatusHandler dataStatusHandler)
        {
            if (dataPoints != null && dataPoints.Count > 0)
            {
                HeartDebugHandler.debugLog("There is data to be written: " + dataPoints.Count.ToString());
                //needed values
                HeartDataType dataType    = dataPoints[0].heartType;
                DateTime      currentTime = DateTime.Now;


                string filePath = System.Environment.GetFolderPath(Environment.SpecialFolder.Personal);

                string backingFile = System.IO.Path.Combine(System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal), fileName);
                // TODO: "FILESTORAGE" [0] this needs a better solution, writing to temp and replacing it solves most file loss, but not ram usage, so should probably use appending so you don't need to read the whole file to memory every time
                // TODO: "FILESTORAGE" cont [1]: this should probably use a version of https://stackoverflow.com/a/39562216 but instead of dropping the last few lines, you store them and add them back into the file after adding the new objects

                Java.IO.File file = new Java.IO.File(backingFile);
                if (file.Exists())//if the file exists, delete it.// TODO: "FILESTORAGE" cont [2]: this is probably where it should be split into two different methods, one for storing and creating a new file, and one for 'appending'
                {
                    HeartDebugHandler.debugLog("File already exists, will be overwritten");
                    file.Delete();
                }

                //string debugString = "";

                using (var writer = System.IO.File.CreateText(backingFile))
                {
                    //made these to make the print statements a bit more readable(although they could probably be made better).
                    var indentOne   = "\t";
                    var indentTwo   = "\t\t";
                    var indentThree = "\t\t\t";
                    await writer.WriteLineAsync("{");                                                               //debugString += "{";

                    await writer.WriteLineAsync(indentOne + "\"updated\": \"" + currentTime.ToString("O") + "\","); //debugString += indentOne + "\"updated\": \"" + currentTime.ToString("O") + "\",";

                    await writer.WriteLineAsync(indentOne + "\"dataType\": \"" + dataType.ToString("G") + "\",");   //debugString += indentOne + "\"dataType\": \"" + dataType.ToString("G") + "\",";

                    await writer.WriteLineAsync(indentOne + "\"data\": [");                                         //debugString += indentOne + "\"data\": [";

                    for (int i = 0; i < dataPoints.Count; i++)
                    {
                        HeartDataPoint point = dataPoints[i];
                        await writer.WriteLineAsync(indentTwo + "{");                                                               //debugString += indentTwo + "{";

                        await writer.WriteLineAsync(indentThree + "\"DateTime\": " + "\"" + point.timestamp.ToString("O") + "\","); //debugString += indentThree + "\"DateTime\": " + "\"" + point.timestamp.ToString("O") + "\",";

                        await writer.WriteLineAsync(indentThree + "\"Value\": " + "\"" + point.amount + "\",");                     //debugString += indentThree + "\"Value\": " + point.amount;

                        await writer.WriteLineAsync(indentThree + "\"accuracy\": " + "\"" + point.accuracy + "\"");

                        string lastLine = "}";
                        if (i < dataPoints.Count - 1)
                        {
                            lastLine += ",";
                        }
                        await writer.WriteLineAsync(indentTwo + lastLine); //debugString += indentTwo + lastLine;
                    }
                    await writer.WriteLineAsync(indentOne + "]");          //debugString += indentOne + "]";

                    await writer.WriteLineAsync("}");                      //debugString += "}";
                }
                dataStatusHandler.updateStatus("File saved");
                //if (debugString != "")
                //{
                //    HeartDebugHandler.debugLog("File that was saved: ");
                //    HeartDebugHandler.debugLog(debugString);
                //}
                //else
                //{
                //    HeartDebugHandler.debugLog("debug string contained nothing");
                //}
            }
            else
            {
                HeartDebugHandler.debugLog("No data to write, operation cancelled");
                dataStatusHandler.updateStatus("No data to store");
            }
        }
        /// <summary>
        /// Reads data from a file, and converts it into instances of the HeartData class, then returns an awaitable task with that data at the end of it.
        /// </summary>
        /// <param name="fileName">The filename of the file that is to be read.</param>
        /// <returns></returns>
        private static async Task <List <HeartDataPoint> > ReadDataPointsTask(string fileName)
        {
            string backingFile = System.IO.Path.Combine(System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal), fileName);

            HeartDebugHandler.debugLog("File to read: " + backingFile);

            if (backingFile == null || !System.IO.File.Exists(backingFile))
            {
                HeartDebugHandler.debugLog("File does not exist");
                //REMARK: this is checked against, so make sure you know what you do if you do any change to return value
                return(null); //cancel operation
            }
            HeartDebugHandler.debugLog("file exists");
            List <HeartDataPoint> dataPoints = new List <HeartDataPoint>();

            using (var reader = new StreamReader(backingFile, true))
            {
                string        line;
                HeartDataType dataType    = HeartDataType.None;
                DateTime?     date        = null;
                string        accuracy    = null;
                int           value       = -1;
                bool          dataReached = false;
                bool          param1Found = false;
                bool          param2Found = false;
                bool          param3Found = false;

                //TODO: move this into the class definition of the dataclass, probably as a builder/factory or some fitting pattern, probably a better place to handle it.
                while ((line = await reader.ReadLineAsync()) != null)
                {
                    if (!dataReached && line.Contains("dataType"))
                    {
                        string[] types = line.Split(":");
                        if (types.Length < 2)
                        {
                            HeartDebugHandler.debugLog("file error, nothing after datatype");
                            break;
                        }
                        string type = line.Split(":")[1];
                        //HeartDebugHandler.debugLog("type: " + type);
                        int first = type.IndexOf("\"") + 1;
                        //HeartDebugHandler.debugLog("first: " + first);
                        int last = type.LastIndexOf("\"");
                        //HeartDebugHandler.debugLog("last: " + last);
                        int length = last - first;
                        //HeartDebugHandler.debugLog("length: " + length);
                        string typeVal = type.Substring(first, length);

                        //HeartDebugHandler.debugLog("typeVal: " + typeVal);
                        dataType = (HeartDataType)Enum.Parse(typeof(HeartDataType), typeVal); //will crash if no match exists
                        //HeartDebugHandler.debugLog("dataType: " + dataType.ToString("G"));
                    }
                    else if (!dataReached && line.Contains("["))
                    {
                        dataReached = true;
                    }

                    if (dataReached)
                    {
                        if (line.Contains("DateTime"))
                        {
                            param1Found = true;
                            //HeartDebugHandler.debugLog("line: " + line);
                            string dateString = line.Split(new[] { ':' }, 2)[1];
                            int    first      = dateString.IndexOf("\"") + 1;
                            int    last       = dateString.LastIndexOf("\"");
                            int    length     = last - first;
                            //HeartDebugHandler.debugLog("Breakpoint");
                            dateString = dateString.Substring(first, length);
                            //HeartDebugHandler.debugLog("Breakpoint");
                            date = DateTime.Parse(dateString, null, DateTimeStyles.RoundtripKind);
                            //HeartDebugHandler.debugLog("Breakpoint");
                        }

                        if (param1Found && line.Contains("Value"))
                        {
                            param2Found = true;
                            //HeartDebugHandler.debugLog("line: " + line);
                            string valueString = line.Split(":")[1];
                            //HeartDebugHandler.debugLog("Breakpoint");
                            valueString = valueString.Replace("\"", "");
                            valueString = valueString.Replace(" ", "");
                            valueString = valueString.Replace(",", "");
                            //HeartDebugHandler.debugLog("Breakpoint");
                            value = int.Parse(valueString);
                        }

                        if (param1Found && param2Found && line.Contains("accuracy"))
                        {
                            param3Found = true;
                            string accuracyString = line.Split(new[] { ':' }, 2)[1];
                            int    first          = accuracyString.IndexOf("\"") + 1;
                            int    last           = accuracyString.LastIndexOf("\"");
                            int    length         = last - first;
                            accuracy = accuracyString.Substring(first, length);
                        }

                        if (param1Found && param2Found && param3Found)
                        {
                            if (dataType != HeartDataType.None && value != -1 && date.HasValue)
                            {
                                HeartDataPoint dataPoint = new HeartDataPoint(dataType, value, (DateTime)date, accuracy);
                                //HeartDebugHandler.debugLog("Breakpoinmarker");
                                dataPoints.Add(dataPoint);

                                //dataType = HeartDataType.None;
                                value       = -1;
                                date        = null;
                                param1Found = false;
                                param2Found = false;
                            }
                        }

                        if (line.Contains("]"))//implicit "&& dataReached"
                        {
                            dataReached = false;
                        }
                    }
                }
            }

            return(dataPoints); //return actual value
        }
Beispiel #19
0
 public void onPurgeStepsData(View view)
 {
     HeartDebugHandler.debugLog("Purge Steps data clicked!");
     HeartFileHandler.DeleteStepsData();
 }
Beispiel #20
0
 public void onPurgeHeartRateData(View view)
 {
     HeartDebugHandler.debugLog("Purge Heart Rate data clicked!");
     HeartFileHandler.DeleteHeartRateData();
 }
Beispiel #21
0
 public void onPurgeAllData(View view)
 {
     HeartDebugHandler.debugLog("Purge all data clicked!");
     HeartFileHandler.DeleteAllData();
 }
Beispiel #22
0
 /// <summary>
 /// Connection was suspended it pretty much just notifies user about this
 /// </summary>
 /// <param name="cause"></param>
 public void OnConnectionSuspended(int cause)
 {
     HeartDebugHandler.debugLog("Connection to Google API client was suspended");
     //updateConnectionStatusString("Connection Suspended");
     connectionStatusHandler.updateStatus("Connection Suspended");
 }
Beispiel #23
0
        /// <summary>
        /// get's called when data from the wearable is received
        /// needs to be different from earlier data, which is why you need the timestamps as part of the data if you want each data point
        /// </summary>
        /// <param name="dataEvents"></param>
        public void OnDataChanged(DataEventBuffer dataEvents)
        {
            HeartDebugHandler.debugLog("Data changed");

            var dataEvent = Enumerable.Range(0, dataEvents.Count)
                            .Select(i => dataEvents.Get(i).JavaCast <IDataEvent>())
                            .FirstOrDefault(x => x.Type == DataEvent.TypeChanged && x.DataItem.Uri.Path.Equals(DataPointsPath));

            if (dataEvent == null)
            {
                return;
            }
            else
            {
                var    dataMapItem = DataMapItem.FromDataItem(dataEvent.DataItem);
                var    map         = dataMapItem.DataMap;
                string message     = dataMapItem.DataMap.GetString("Message");
                HeartDebugHandler.debugLog("Data received! message: " + message);

                string[] allDataPoints;
                if (message.Contains("|"))
                {
                    allDataPoints = message.Split("|");
                }
                else
                {
                    allDataPoints = new[] { message };
                }

                int  teller       = 0;
                bool stepReceived = false;
                bool hbReceived   = false;
                bool hrReceived   = false;
                foreach (string pointData in allDataPoints)
                {
                    HeartDataPoint p = decodeDataPoint(pointData);
                    if (p != null)
                    {
                        teller++;
                    }

                    if (p.heartType == HeartDataType.HeartBeat)
                    {
                        if (!hbReceived)
                        {
                            hbReceived = true;
                        }
                        hdata_Beat.Enqueue(p);

                        if (hdata_Beat.Count > 50)
                        {
                            HeartFileHandler.saveData(hdata_Beat, HeartFileHandler.FILENAME_HEARTBEAT, dataStatusHandler);
                        }
                    }
                    else if (p.heartType == HeartDataType.HeartRate)
                    {
                        if (!hrReceived)
                        {
                            hrReceived = true;
                        }
                        hdata_Rate.Enqueue(p);

                        if (hdata_Rate.Count > 50)
                        {
                            HeartFileHandler.saveData(hdata_Rate, HeartFileHandler.FILENAME_HEARTRATE, dataStatusHandler);
                        }
                    }
                    else if (p.heartType == HeartDataType.StepCount)
                    {
                        if (!stepReceived)
                        {
                            stepReceived = true;
                        }
                        hdata_Steps.Enqueue(p);
                        if (hdata_Steps.Count > 50)
                        {
                            HeartFileHandler.saveData(hdata_Steps, HeartFileHandler.FILENAME_STEPS, dataStatusHandler);
                        }
                    }
                }

                if (teller > 0)
                {
                    string types = "";
                    if (hrReceived)
                    {
                        types += "HR,";
                    }
                    if (hbReceived)
                    {
                        types += "HB,";
                    }
                    if (stepReceived)
                    {
                        types += "St";
                    }
                    //updateStatusString("Data received, Types: {"+ types + "}, Amount: " + teller + ".");
                    connectionStatusHandler.updateStatus("Data received, Types: {" + types + "}, Amount: " + teller + ".");
                    //saveStepData();//bør nok kjøres på en mer intelligent måte
                }
                else
                {
                    //updateStatusString("Invalid data received.");
                    connectionStatusHandler.updateStatus("Invalid data received.");
                }
            }
        }
        /// <summary>
        /// Takes in a list(QUEUE) and stores it in a file with the provided filename, it then updates the application status(TextView) to make the user aware the file has been saved
        /// </summary>
        /// <param name="hdata">The list of items to be stored</param>
        /// <param name="filename">The filename of the file to store the data in</param>
        /// <param name="dataStatusHandler">the handler of the textview for statuses in the app gui</param>
        public static async void saveData(Queue <HeartDataPoint> hdata, string filename, StatusHandler dataStatusHandler)
        {
            bool cancelOp = false; //if this trips to true, then file won't be stored
            int  selected = -1;


            //handling of "file already being manipulated" checks
            switch (filename)
            {
            case FILENAME_STEPS: selected = 0;
                break;

            case FILENAME_HEARTBEAT: selected = 1;
                break;

            case FILENAME_HEARTRATE: selected = 2;
                break;
            }

            if (selected != -1 && beingSaved[selected] == null)
            {
                beingSaved[selected] = filename;
            }
            else
            {
                cancelOp = true;
            }
            //first file manip check done

            if (!cancelOp)//if file is being manipulated, don't continue
            {
                HeartDebugHandler.debugLog("Save start");
                List <HeartDataPoint> existingData;
                HeartDebugHandler.debugLog("Reading existing data start");
                existingData = await ReadDataPointsTask(filename);

                HeartDebugHandler.debugLog("Reading existing data finished");
                HeartDebugHandler.debugLog("Merging the two datasets");
                if (existingData == null)
                {
                    existingData = new List <HeartDataPoint>();
                }
                else
                {
                    if (existingData.Count > 0)
                    {
                        HeartDebugHandler.debugLog("There was existing data, amount" + existingData.Count.ToString());
                        HeartDebugHandler.debugLog("First datapoint contained: " + existingData[0].heartType.ToString("G") + ";" + existingData[0].amount.ToString() + ";" + existingData[0].timestamp + ".");
                    }
                }
                while (hdata.Any())
                {
                    HeartDataPoint element = hdata.Dequeue();
                    existingData.Add(element);
                }
                HeartDebugHandler.debugLog("Datasets have been merged, final tally: " + existingData.Count.ToString());
                HeartDebugHandler.debugLog("Actually writing the file");
                await storeDataPointsTask(existingData, filename, dataStatusHandler);


                //now reset the file being saved to null, so that the program knows it can be used again
                //TODO: look into whether this can all be handled using a callback instead, and whether that's more efficient
                if (filename.Equals(FILENAME_STEPS))
                {
                    beingSaved[0] = null;
                }
                else if (filename.Equals(FILENAME_HEARTBEAT))
                {
                    beingSaved[1] = null;
                }
                else if (filename.Equals(FILENAME_HEARTRATE))
                {
                    beingSaved[2] = null;
                }
            }
            else
            {
                //setting the status TextView to this string
                dataStatusHandler.updateStatus("Data already being saved");
            }
        }
        /// <summary>
        /// the callback that happens when any data has been sent, so going through event args to see what, and generating a response display to client based on the result of that data upload.
        /// then it starts the upload for the next type, and when all uploads have completed(as in connection has been terminated) it finishes and updates the UI.
        /// so sort of recursive
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        public void dataUploadedCallback(object sender, UploadValuesCompletedEventArgs e)
        {
            if (e != null)
            {
                try
                {
                    var crasha = e.Result;
                    HeartDebugHandler.debugLog("Crasha ikke");
                }
                catch (System.Reflection.TargetInvocationException exception)
                {
                    var crash = exception.InnerException;
                    if (crash != null)
                    {
                        HeartDebugHandler.debugLog(crash.ToString());
                    }

                    //HeartDebugHandler.debugLog("halt");
                }

                HeartDebugHandler.debugLog("e was not null");
                if (e.Result != null)
                {
                    HeartDebugHandler.debugLog("e.Result was not null");
                    byte[] result     = e.Result;
                    string resultText = Encoding.UTF8.GetString(result);
                    HeartDebugHandler.debugLog(resultText);

                    if (e.UserState.ToString().Equals(stepsToken))
                    {
                        stepsReceived = true;
                    }
                    else if (e.UserState.ToString().Equals(heartRateToken))
                    {
                        hrReceived = true;
                    }
                    else if (e.UserState.ToString().Equals(heartbeatToken))
                    {
                        hbReceived = true;
                    }



                    //TOAST HERE
                    if (resultText.Length == 5)
                    {
                        //Toast.MakeText(context, "Code: " + resultText, ToastLength.Long).Show();
                        //codeView.Text = resultText;
                        //codeView.Visibility = ViewStates.Visible;

                        if (e.UserState.ToString().Equals(stepsToken))
                        {
                            stepsResult = resultText;
                        }
                        else if (e.UserState.ToString().Equals(heartRateToken))
                        {
                            hrResult = resultText;
                        }
                        else if (e.UserState.ToString().Equals(heartbeatToken))
                        {
                            hbResult = resultText;
                        }
                    }
                    else
                    {
                        Toast.MakeText(context, "Upload failed, response: " + resultText, ToastLength.Long).Show();
                        codeView.Text       = "Upload Failed..";
                        codeView.Visibility = ViewStates.Visible;
                    }
                }
                else
                {
                    HeartDebugHandler.debugLog("e.Result was null");
                    HeartDebugHandler.debugLog("e.Error: " + e.Error);
                }
            }
            else
            {
                HeartDebugHandler.debugLog("e was null, skipping the rest");
                stepsReceived = true;
                hbReceived    = true;
                hrReceived    = true;
            }


            if (stepsReceived && !hbReceived)
            {
                using (var heartBeatClient = new WebClient())
                {
                    var heartBeatValues = new NameValueCollection();
                    heartBeatValues.Add("hdatatype", "Heartbeat");
                    DateTime now = DateTime.Now;
                    heartBeatValues.Add("hupdated", now.ToString("o"));
                    heartBeatValues.Add("hdatapoints", heartBeatDataString);
                    heartBeatClient.Headers[HttpRequestHeader.Accept] =
                        "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8";
                    heartBeatClient.UploadValuesCompleted += dataUploadedCallback;
                    heartBeatClient.UploadValuesAsync(new Uri(url), "POST", heartBeatValues, heartbeatToken);
                }
            }

            if (hbReceived && stepsReceived && !hrReceived)
            {
                using (var heartRateClient = new WebClient())
                {
                    var heartRateValues = new NameValueCollection();
                    heartRateValues.Add("hdatatype", "HeartRate");
                    DateTime now = DateTime.Now;
                    heartRateValues.Add("hupdated", now.ToString("o"));
                    heartRateValues.Add("hdatapoints", heartRateDataString);
                    heartRateClient.Headers[HttpRequestHeader.Accept] =
                        "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8";
                    heartRateClient.UploadValuesCompleted += dataUploadedCallback;
                    heartRateClient.UploadValuesAsync(new Uri(url), "POST", heartRateValues, heartRateToken);
                }
            }

            if (stepsReceived && hbReceived && hrReceived)
            {
                updateUIWithData();
            }
        }