//TODO register this with an event in messenger class /// <summary>Loads device and sensor info from the DB.</summary> /// <remarks>Don't make publish or call directly! always push onto the task!</remarks> /// <returns>True if it loaded something, false otherwise.</returns> private void LoadData() { LoggingService.LogInfo("DatapointsSaver refreshing cache", Windows.Foundation.Diagnostics.LoggingLevel.Information); using (var db = new MainDbContext()) { _dbDevices = db.Devices.Include(dv => dv.Sensors).Include(dv => dv.Relays).AsNoTracking().ToList(); var sensorsHistory = db.SensorsHistory.Where(sh => sh.TimeStamp > Today).ToList(); // we will edit this _sensorTypes = db.SensorTypes.Include(st => st.Param).Include(st => st.Place).AsNoTracking().ToList(); //Add missing sensors and relays foreach (var sensor in _dbDevices.SelectMany(dv => dv.Sensors)) { if (_sensorBuffer.Any(sb => sb.Sensor.ID == sensor.ID) == false) { _sensorBuffer.Add(new SensorBuffer(sensor)); } } //TODO merge the datapoints! foreach (var sHistory in sensorsHistory) { sHistory.DeserialiseData(); var mIndex = _sensorBuffer.FindIndex(sb => sb.Sensor.ID == sHistory.SensorID); if (_sensorBuffer[mIndex].DataDay == null || _sensorBuffer[mIndex].DataDay.TimeStamp < sHistory.TimeStamp) { _sensorBuffer[mIndex] = new SensorBuffer(_sensorBuffer[mIndex].Sensor, sHistory); } else if (_sensorBuffer[mIndex].DataDay.Data != null && sHistory.Data != null) { var sHistMerged = SensorHistory.Merge(_sensorBuffer[mIndex].DataDay, sHistory); _sensorBuffer[mIndex] = new SensorBuffer(_sensorBuffer[mIndex].Sensor, sHistMerged); } } } }
public void BufferAndSendReadings(KeyValuePair <Guid, SensorMessage[]> values, string deviceName) { //Purposefull fire and forget _localTask = _localTask.ContinueWith(previous => { var device = _dbDevices.FirstOrDefault(dv => dv.SerialNumber == values.Key); if (device == null) { CreateDevice(values, deviceName); } else { var sensorReadings = new List <BroadcasterService.SensorReading>(); foreach (var message in values.Value) { try { var SensorObject = device.Sensors.FirstOrDefault(sen => sen.SensorTypeID == message.SensorTypeID); SensorBuffer sensorBuffer = _sensorBuffer.FirstOrDefault(sb => sb.Sensor.ID == SensorObject.ID); if (SensorObject == null || sensorBuffer == null) { Util.LoggingService.LogInfo($"Device has a new sensor with typeID {message.SensorTypeID}, however adding sensors is not supported yet.", Windows.Foundation.Diagnostics.LoggingLevel.Error); break; } var duration = TimeSpan.FromMilliseconds((double)message.duration / 1000); var timeStamp = DateTimeOffset.Now; var datapoint = new SensorDatapoint(message.value, timeStamp, duration); sensorBuffer.FreshBuffer.Add(datapoint); var sensorReading = new BroadcasterService.SensorReading(sensorBuffer.Sensor.ID, datapoint.Value, datapoint.TimeStamp, datapoint.Duration); sensorReadings.Add(sensorReading); } catch (ArgumentNullException) { //TODO add a new sensor to the device! } } //this is meant to be fire-forget, that's cool #pragma warning disable CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed WebSocketConnection.Instance.SendAsync(sensorReadings); BroadcasterService.Instance.NewSensorDataPoint.Invoke(sensorReadings); #pragma warning restore CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed } }); }
//Closes sensor Histories that are no longer usefull private void SaveBufferedReadings(object sender, object e) { LoggingService.LogInfo($"Saved Buffered Readings: {DateTimeOffset.Now.DateTime} Datapointsaver", Windows.Foundation.Diagnostics.LoggingLevel.Information); _localTask = _localTask.ContinueWith(previous => { //if (Settings.Instance.LastSuccessfulGeneralDbGet > DateTimeOffset.Now - TimeSpan.FromMinutes(5)) //{ LoggingService.LogInfo("Datasaver started, did not bother detecting a recent update.", Windows.Foundation.Diagnostics.LoggingLevel.Verbose); using (var db = new MainDbContext()) { for (var i = 0; i < _sensorBuffer.Count; i++) { var sbuffer = _sensorBuffer[i]; SensorDatapoint sensorDatapoint = null; if (sbuffer.FreshBuffer.Count > 0) { var startTime = sbuffer.FreshBuffer[0].TimeStamp; var endTime = sbuffer.FreshBuffer.Last().TimeStamp; var duration = (endTime - startTime).Subtract(sbuffer.FreshBuffer[0].Duration); var cumulativeDuration = TimeSpan.Zero; double cumulativeValue = 0; for (var b = 0; b < sbuffer.FreshBuffer.Count; b++) { cumulativeDuration += sbuffer.FreshBuffer[b].Duration; cumulativeValue += sbuffer.FreshBuffer[b].Value; } var sensorType = _sensorTypes.First(st => st.ID == sbuffer.Sensor.SensorTypeID); var value = cumulativeValue / sbuffer.FreshBuffer.Count; if (sensorType.ParamID == 5) // Level { sensorDatapoint = new SensorDatapoint(Math.Round(value), endTime, duration); } else if (sensorType.ParamID == 9) //water flow { sensorDatapoint = new SensorDatapoint(value, endTime, cumulativeDuration); } else { sensorDatapoint = new SensorDatapoint(value, endTime, duration); } sbuffer.FreshBuffer.RemoveRange(0, sbuffer.FreshBuffer.Count); } //only if new data is present if (sensorDatapoint != null) { //check if corresponding dataDay is too old or none exists at all if (sbuffer.DataDay?.TimeStamp < sensorDatapoint.TimeStamp || sbuffer.DataDay == null) { var dataDay = new SensorHistory { LocationID = sbuffer.Sensor.Device.LocationID, SensorID = sbuffer.Sensor.ID, Sensor = sbuffer.Sensor, TimeStamp = Tomorrow, Data = new List <SensorDatapoint>() }; _sensorBuffer[i] = new SensorBuffer(sbuffer.Sensor, dataDay); //Only uses this entity, and does not follow the references to stick related references in the DB db.Entry(dataDay).State = EntityState.Added; } else { //this will not attach related entities, which is good db.Entry(sbuffer.DataDay).State = EntityState.Unchanged; } _sensorBuffer[i].DataDay.Data.Add(sensorDatapoint); _sensorBuffer[i].DataDay.SerialiseData(); } } //for loop ends //Once we are done here, mark changes to the db db.SaveChanges(); LoggingService.LogInfo("Saved Sensor Data", Windows.Foundation.Diagnostics.LoggingLevel.Verbose); } //} //else //{ // Debug.WriteLine("Skipped datasaver due to lack of recent update."); //} }); }