Exemple #1
0
        /// <summary>Gets all histories between and including the datetime given.</summary>
        /// <param name="fromDateTimeUnixSeconds">The earliest time to include datapoints.</param>
        /// <param name="toUtcDateTimeUnixSeconds">The latest time to include dataopints.</param>
        /// <returns>All the histories between the specified times.</returns>
        public async Task <IActionResult> GetUserHistories(long fromDateTimeUnixSeconds, long toUtcDateTimeUnixSeconds)
        {
            // Filter by the UTC Date (time 00:00:00 (==12:00am)).
            // All times are converted to the starting time of the day.
            var fromDateTime = DateTimeOffset.FromUnixTimeSeconds(fromDateTimeUnixSeconds);
            var fromDate     = fromDateTime.Date;
            var toDateTime   = DateTimeOffset.FromUnixTimeSeconds(toUtcDateTimeUnixSeconds);
            var toDate       = toDateTime.Date;

            // Prepare to filter by locations owned by the user.
            var user = await _userManager.GetUserAsync(User);

            var userId      = new Guid(user.Id);
            var locationIds = await _db.Locations.Where(l => l.PersonId == userId).Select(l => l.Id).ToListAsync();

            var data =
                await
                _db.SensorHistories.Where(
                    h => locationIds.Contains(h.LocationId) && (h.UtcDate >= fromDate) && (h.UtcDate <= toDate))
                .ToListAsync();

            var needsSlicing = data.Where(h => (h.UtcDate == fromDate) || (h.UtcDate == toDate));

            foreach (var history in needsSlicing)
            {
                var sliced = SensorDatapoint.Slice(history.RawData, fromDateTime, toDateTime);
                history.RawData = sliced;
            }

            return(new JsonResult(data));
        }
        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
                }
            });
        }
Exemple #3
0
        public async Task <IActionResult> SetUserHistories([FromBody] List <SensorHistory> histories)
        {
            var user = await _userManager.GetUserAsync(User);

            var userId      = new Guid(user.Id);
            var locationIds = await _db.Locations.Where(l => l.PersonId == userId).Select(l => l.Id).ToListAsync();

            if (histories.Any(h => !locationIds.Contains(h.LocationId)))
            {
                var message = "Cant save histories at locations not owned by user.";
                _logger.LogError(message);
                return(BadRequest(message));
            }

            // Composite keys aren't easy to turn into a query.
            var historyIds = histories.Select(h => $"{h.SensorId},{h.UtcDate.Ticks}");

            var existsInDb = await _db.SensorHistories
                             .Where(h => historyIds.Contains($"{h.SensorId},{h.UtcDate.Ticks}"))
                             .ToListAsync();

            var itemsToUpdate = new List <SensorHistory>();

            foreach (var dbHistory in existsInDb)
            {
                // Removed the already existing item from the histories recieved from the API.
                var recievedHist =
                    histories.First(h => (h.UtcDate == dbHistory.UtcDate) && (h.SensorId == dbHistory.SensorId));
                histories.Remove(recievedHist);

                var mergedData = SensorDatapoint.Merge(dbHistory.RawData, recievedHist.RawData);

                // Merge the data in the newly recieved data which should have an updated UploadedAt.
                recievedHist.RawData = mergedData;
                if (recievedHist.UploadedAt < DateTimeOffset.Now - TimeSpan.FromMinutes(5))
                {
                    return(BadRequest("UploadedAt time was not set or significant lag has occured."));
                }
                itemsToUpdate.Add(recievedHist);
            }

            // The remaining items left in histories must all be new.
            _db.SensorHistories.AddRange(histories);
            _db.SensorHistories.UpdateRange(itemsToUpdate);
            await _db.SaveChangesAsync();

            return(Ok());
        }
        public void BufferAndSendReadings(KeyValuePair <Guid, Manager.SensorMessage[]> values)
        {
            //Purposefull fire and forget
            _localTask = _localTask.ContinueWith(previous =>
            {
                var device = _dbDevices.FirstOrDefault(dv => dv.SerialNumber == values.Key);

                if (device == null)
                {
                    CreateDevice(values);
                }
                else
                {
                    var sensorReadings = new List <Messenger.SensorReading>();
                    foreach (var message in values.Value)
                    {
                        try
                        {
                            var sensorBuffer = _sensorBuffer.First(sb => sb.Sensor.SensorTypeID == message.SensorTypeID);
                            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 Messenger.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);
                    Messenger.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.");
                //}
            });
        }
 public BindableDatapoint(SensorDatapoint datapoint)
 {
     timestamp = datapoint.TimeStamp.LocalDateTime;
     value     = datapoint.Value;
 }