public IEnumerable <Reading> GetReadings(string stationId, DateTime date, LookBack lookBack = LookBack.Day)
        {
            var startDate = date.AddDays(-(int)lookBack);

            using var con = new SQLiteConnection(@"URI=file:" + _configuration["DatabasePath"]);
            con.Open();

            using var cmd   = new SQLiteCommand(con);
            cmd.CommandText = "SELECT timestamp, temperature, humidity FROM dht_data WHERE station = @station AND timestamp >= @startTimestamp AND timestamp < @endTimestamp ORDER BY timestamp ASC LIMIT 30000;";

            cmd.Parameters.AddWithValue("@station", stationId);
            cmd.Parameters.AddWithValue("@startTimestamp", ((DateTimeOffset)startDate).ToUnixTimeSeconds());
            cmd.Parameters.AddWithValue("@endTimestamp", ((DateTimeOffset)date).ToUnixTimeSeconds());
            cmd.Prepare();

            using SQLiteDataReader rdr = cmd.ExecuteReader();

            while (rdr.Read())
            {
                yield return(new Reading
                {
                    Timestamp = rdr.GetInt64(0),
                    Temperature = rdr.GetDouble(1),
                    Humidity = rdr.GetInt32(2),
                });
            }

            con.Close();
        }
        private async Task CheckMeter(long size, CancellationToken cancellationToken)
        {
            if (BytesSent <= AverageBytesPerSecond)
            {
                DateTime meterTime = DateTime.Now.Subtract(LookBackWindow);

                var current = LookBack.First;

                while (!cancellationToken.IsCancellationRequested && current != null && current.Value.Time <= meterTime)
                {
                    BytesSent -= current.Value.Value;
                    EventCount--;
                    current = current.Next;
                    LookBack.RemoveFirst();
                }
            }

            LookBack.AddLast(new MeterItem <long>(size));
            BytesSent += size;
            EventCount++;

            var time = (DateTime.UtcNow - LookBack.First.Value.Time).TotalMilliseconds;

            if (BytesSent / time >= AverageBytesPerSecond)
            {
                await Backoff(cancellationToken);
            }
        }
        public ActionResult Get(string stationId, string dateString, LookBack lookBack)
        {
            ViewBag.DateString = dateString;
            ViewBag.StationId  = stationId;
            ViewBag.LookBack   = lookBack;

            return(View());
        }
        public Dictionary <string, double[][]> GetDay(string stationId, string dateString, LookBack lookBack)
        {
            var date = DateTime.ParseExact(dateString, "yyyy-MM-dd", CultureInfo.InvariantCulture);

            var readings = GetReadings(stationId, date, lookBack).ToArray();

            return(new Dictionary <string, double[][]>
            {
                { "Temperature", readings.Select(x => new double[] { x.Timestamp * 1000, x.Temperature }).ToArray() },
                { "Humidity", readings.Select(x => new double[] { x.Timestamp * 1000, x.Humidity }).ToArray() },
            });
        }