/// <summary> /// This method process the FullData. Once the last byte is received, we process the consolidated array. /// </summary> private void ProcessData() { //WeakHashMap don't need the Tomato Header part byte[] data = Arrays.CopyOfRange(this.FullData, TOMATO_HEADER_LENGTH, TOMATO_HEADER_LENGTH + 344); // MIAOMIAO PROTOCOL : The 4th byte is where the sensor status is. // TODO : Quoi faire ici ? On abandonne la lecture ? Noon ... --> no one no oneeeeeee ne sait if (!FreeStyleLibreUtils.IsSensorReady(data[4])) { Log.Debug(LOG_TAG, "MiaoMiaoProtocol.ProcessData: Sensor is not ready, we should Ignoring reading!"); } // Here we are !! The show is about to begin :D // MIAOMIAO Protocol long now = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(); ReadingSession.LastReadingTimestamp = now; // MIAOMIAO Protocol. Trend index is at the 26th index int indexTrend = data[26] & 0xFF; // MIAOMIAO Protocol. History index is at the 27th index int indexHistory = data[27] & 0xFF; // MIAOMIAO Protocol. SensorTime is at 317th and 316th index int sensorTime = 256 * (data[317] & 0xFF) + (data[316] & 0xFF); long sensorStartTime = now - sensorTime * this.settings.MILLISECONDS_IN_MINUTE; Log.Debug(LOG_TAG, "MiaoMiaoProtocol.ProcessFullData: sensorTime=[" + sensorTime + "]"); // option to use 13 bit mask bool thirteen_bit_mask = true; // loads history values (ring buffer, starting at index_trent. byte 124-315) for (int index = 0; index < 32; index++) { int i = indexHistory - index - 1; if (i < 0) { i += 32; } GlucoseMeasure measure = new GlucoseMeasure { GlucoseLevelRaw = FreeStyleLibreUtils.ExtractGlucoseRaw(new byte[] { data[(i * 6 + 125)], data[(i * 6 + 124)] }, thirteen_bit_mask), }; // we don't need null values if (measure.GlucoseLevelRaw == 0) { continue; } int time = Math.Max(0, Math.Abs((sensorTime - 3) / 15) * 15 - index * 15); measure.Timestamp = sensorStartTime + time * this.settings.MILLISECONDS_IN_MINUTE; measure.RealDateTimeOffset = DateTimeOffset.FromUnixTimeMilliseconds(sensorStartTime + time * this.settings.MILLISECONDS_IN_MINUTE); measure.SensorTime = time; measure.GlucoseLevelMGDL = (float)Math.Round((decimal)measure.GlucoseLevelRaw / 10); measure.GlucoseLevelMMOL = (float)FreeStyleLibreUtils.ConvertMGDLToMMolPerLiter(this.settings, Math.Round((double)measure.GlucoseLevelRaw / 10)); ReadingSession.PushHistoryMeasure(measure); } // loads trend values (ring buffer, starting at index_trent. byte 28-123) for (int index = 0; index < 16; index++) { int i = indexTrend - index - 1; if (i < 0) { i += 16; } GlucoseMeasure measure = new GlucoseMeasure { GlucoseLevelRaw = FreeStyleLibreUtils.ExtractGlucoseRaw(new byte[] { data[(i * 6 + 29)], data[(i * 6 + 28)] }, thirteen_bit_mask) }; // we don't need null values if (measure.GlucoseLevelRaw == 0) { continue; } int time = Math.Max(0, sensorTime - index); measure.RealDateTimeOffset = DateTimeOffset.FromUnixTimeMilliseconds(sensorStartTime + time * this.settings.MILLISECONDS_IN_MINUTE); measure.Timestamp = sensorStartTime + time * this.settings.MILLISECONDS_IN_MINUTE; measure.SensorTime = time; measure.GlucoseLevelMGDL = (float)Math.Round((decimal)measure.GlucoseLevelRaw / 10); measure.GlucoseLevelMMOL = (float)FreeStyleLibreUtils.ConvertMGDLToMMolPerLiter(this.settings, Math.Round((double)measure.GlucoseLevelRaw / 10)); ReadingSession.PushTrendMeasure(measure); Log.Debug(LOG_TAG, $"MiaoMiaoProtocol.ProcessData: measure=[{measure.ToString()}"); } // The current measure if (ReadingSession.TrendMeasures.Count > 0) { ReadingSession.CurrentMeasure = ReadingSession.TrendMeasures[0]; } ReadingSession.CalculateSmothedData5Points(); // At the end, we end the ReadingMesureSession ReadingSession.End(); // send the event to notify that the reading is over this.EventAggregator.GetEvent <EndReadingEvent>().Publish(""); // Notify the GlucoseService that it's done this.GlucoseService.HandleReadingSession(ReadingSession); }
/// <summary> /// This method processes the glucose measures /// </summary> /// <param name="userId">The userId</param> /// <param name="freshMeasures">The list of the fresh measures</param> public void ProcessMeasuresData(string userId, MeasureReadingSession readingSession) { var currentUser = this.userRepository.GetCurrentUser(); var userSettings = this.userSettingsRepository.GetCurrentUserSettings(); bool isCreation = false; // first, we check the age of the sensor var currentSensor = this.sensorRepository.GetCurrentSensor(); long newSensorAge = readingSession.TrendMeasures[readingSession.TrendMeasures.Count - 1].SensorTime; long savedSensorAge = currentSensor.Age; if (newSensorAge > savedSensorAge) { Log.Debug(LOG_TAG, GetType() + ".ProcessMeasuresData: Sensor age has advanced. Try to insert measures" + savedSensorAge); savedSensorAge = newSensorAge; this.sensorRepository.UpdateSensorAge(currentSensor, savedSensorAge); } else if (newSensorAge == savedSensorAge) { Log.Debug(LOG_TAG, GetType() + ".ProcessMeasuresData: Sensor age has not advanced. sensorAge=[" + savedSensorAge + "]"); return; // do not try to insert again } else { Log.Debug(LOG_TAG, GetType() + ".ProcessMeasuresData: Sensor age has gone backwards!!! " + savedSensorAge); savedSensorAge = newSensorAge; this.sensorRepository.UpdateSensorAge(currentSensor, savedSensorAge); } GlucoseMeasure lastInsertedMeasure = this.glucoseMeasureRepository.GetLastMeasureByUser(userId); // create each GlucoseMeasure foreach (GlucoseMeasure measure in readingSession.GetAllMeasures()) { if (lastInsertedMeasure != null && lastInsertedMeasure.Timestamp > measure.Timestamp) { continue; } // possibly, the trend measures interval could be one minute // we only want 5 minutes interval if (measure.SensorTime % appSettings.MEASURE_NOTIFICATION_INTERVAL != 0) { continue; } isCreation = true; // creation first measure.Id = Guid.NewGuid().ToString(); this.glucoseMeasureRepository.Create(measure, userId); // then updates // measureoffset this.glucoseMeasureRepository.UpdateMeasureOffset(measure, userSettings.MeasureOffset, appSettings); // In The medical zone //medical zone this.glucoseMeasureRepository.ChangeIsInTheMedicalZone(measure, InTheMedicalZone(measure)); Log.Debug(LOG_TAG, GetType() + ".ProcessMeasuresData: Creating measure " + measure.ToString()); } GlucoseMeasure lastGlucoseMeasure = readingSession.CurrentMeasure; //Last glucose measure additionnal setup if (lastGlucoseMeasure.Id == null) { //Add to the last glucose measure an generatedId lastGlucoseMeasure.Id = Guid.NewGuid().ToString(); //Save the last glucose measure into the database this.glucoseMeasureRepository.Create(lastGlucoseMeasure, userId); } if (lastGlucoseMeasure.UserId == null) { //Add to the last glucose measure an userId this.glucoseMeasureRepository.ChangeUserId(lastGlucoseMeasure, userId); } //Check if the measure is in the medical zone this.glucoseMeasureRepository.ChangeIsInTheMedicalZone(lastGlucoseMeasure, InTheMedicalZone(lastGlucoseMeasure)); //Apply the offset lastGlucoseMeasure = this.glucoseMeasureRepository.UpdateMeasureOffset(lastGlucoseMeasure, userSettings.MeasureOffset, appSettings); Log.Debug(LOG_TAG, GetType() + ".ProcessMeasuresData: lastMeasure = " + lastGlucoseMeasure.ToString()); var toPublish = this.appSettings.HANDLE_MGDL_MEASURE ? lastGlucoseMeasure.GlucoseLevelMGDL : lastGlucoseMeasure.GlucoseLevelMMOL; // Spread the current last glucose measure this.eventAggregator.GetEvent <LastMeasureReceivedEvent>().Publish(toPublish); }