private async Task processAsync(SensorMapping mapping, CancellationToken ct)
        {
            var now       = this.m_clock.GetCurrentTime();
            var threshold = mapping.LastProcessed.Add(Interval);
            var end       = roundDown(now, Interval);

            logger.Info($"Processing {mapping.Id}.");

            if (threshold > now)
            {
                logger.Info("Stopped processing. Timestamp threshold past current timestamp.");
                return;
            }

            var resultSet = await this.computeAggregates(mapping, end, ct).ConfigureAwait(false);

            if (resultSet == null)
            {
                return;
            }

            logger.Debug("Finished calculating averages. Starting storage process.");
            await this.storeDataPoints(resultSet, ct).ConfigureAwait(false);

            await this.m_history.CreateProcessingTimestamp(mapping.Id, resultSet.Count, mapping.LastProcessed, end, ct).ConfigureAwait(false);

            await this.cleanupOldRequests(mapping, end, ct).ConfigureAwait(false);

            mapping.LastProcessed = end;

            logger.Info($"Finished processing {mapping.Id}.");
        }
        private async Task <IDictionary <DateTime, DataPoint> > processPowerData(SensorMapping mapping, DateTime end, CancellationToken ct)
        {
            var rawPowerData = await this.m_client.GetRangeAsync(mapping.PowerSensorId, mapping.LastProcessed, end, ct)
                               .ConfigureAwait(false);

            var pwrData = rawPowerData?.ToList();

            logger.Info($"Load {pwrData?.Count} datapoints.");

            if (pwrData == null || pwrData.Count <= 0)
            {
                return(null);
            }

            var resultSet = DataCalculator.ComputePowerAverages(mapping, pwrData);

            var span = pwrData[0].Timestamp - this.m_clock.GetCurrentTime();

            if (span > TimeSpan.FromHours(3))
            {
                return(resultSet);
            }

            // Get the longitude and latitude. Assume these are all the same
            // for other measurements (.. a smart meter is quite unlikely
            // to move).
            var first = pwrData[0].Location;

            await this.lookupWeather(mapping, resultSet, first, ct).ConfigureAwait(false);

            return(resultSet);
        }
        private async Task processGasData(SensorMapping mapping, IDictionary <DateTime, DataPoint> data, DateTime end, CancellationToken ct)
        {
            if (mapping.GasSensorId != null)
            {
                logger.Info("Processing gas data.");
                var gasTask = this.m_client.GetRangeAsync(mapping.GasSensorId, mapping.LastProcessed, end, ct);
                var gasData = await gasTask.ConfigureAwait(false);

                DataCalculator.ComputeGasAverages(data, gasData);
                logger.Debug("Finished processing gas data.");
            }
        }
        private async Task <IDictionary <DateTime, DataPoint> > computeAggregates(SensorMapping mapping, DateTime end, CancellationToken ct)
        {
            var resultSet = await this.processPowerData(mapping, end, ct).ConfigureAwait(false);

            if (resultSet == null)
            {
                logger.Warn("Stopped processing. No E-data received.");
                return(null);
            }

            await this.processEnvData(mapping, resultSet, end, ct).ConfigureAwait(false);

            await this.processGasData(mapping, resultSet, end, ct).ConfigureAwait(false);

            return(resultSet);
        }
示例#5
0
        public static IDictionary <DateTime, DataPoint> ComputePowerAverages(SensorMapping mapping, IEnumerable <Measurement> measurements)
        {
            var groups = measurements.GroupBy(g => new {
                Timestamp = new DateTime(g.Timestamp.Year, g.Timestamp.Month, g.Timestamp.Day, g.Timestamp.Hour,
                                         g.Timestamp.Minute, 0, DateTimeKind.Utc)
            }).Select(x => new {
                x.Key,
                Measurements = x.ToList()
            });

            var datapoints = new SortedDictionary <DateTime, DataPoint>();

            foreach (var group in groups)
            {
                var production     = 0M;
                var consumption    = 0M;
                var energyUsed     = 0M;
                var energyProduced = 0M;
                var tariff         = 0M;

                foreach (var measurement in group.Measurements)
                {
                    production  += measurement.Data[InstantaneousPowerProduction].Value;
                    consumption += measurement.Data[InstantaneousPowerUsage].Value;
                    energyUsed   = measurement.Data[EnergyConsumptionTariff1].Value +
                                   measurement.Data[EnergyConsumptionTariff2].Value;
                    energyProduced = measurement.Data[EnergyProductionTariff1].Value +
                                     measurement.Data[EnergyProductionTariff2].Value;
                    tariff = measurement.Data[Tariff].Value;
                }

                production  /= group.Measurements.Count;
                consumption /= group.Measurements.Count;

                datapoints.Add(group.Key.Timestamp, new DataPoint {
                    PowerProduction  = production,
                    PowerUsage       = consumption,
                    EnergyProduction = energyProduced,
                    EnergyUsage      = energyUsed,
                    Tariff           = tariff > 0M,
                    Timestamp        = group.Key.Timestamp,
                    SensorId         = mapping.Id
                });
            }

            return(datapoints);
        }
        private async Task lookupWeather(SensorMapping mapping, IDictionary <DateTime, DataPoint> resultSet, Location location, CancellationToken ct)
        {
            var lookup = new WeatherLookup {
                Longitude = location.Longitude,
                Latitude  = location.Latitude,
                SensorId  = mapping.Id
            };

            var result = await this.m_openWeather.LookupAsync(lookup, ct).ConfigureAwait(false);

            decimal?oat = null;

            if (result != null)
            {
                oat = Convert.ToDecimal(result.Temperature);
            }

            foreach (var keyValuePair in resultSet)
            {
                keyValuePair.Value.OutsideAirTemperature = oat;
            }
        }
        private async Task cleanupOldRequests(SensorMapping mapping, DateTime lastProcessingTime, CancellationToken ct)
        {
            if (mapping.LastProcessed.Hour != lastProcessingTime.Hour)
            {
                await this.m_client.DeleteBucketsAsync(mapping.PowerSensorId, DateTime.MinValue, lastProcessingTime, ct)
                .ConfigureAwait(false);

                if (!string.IsNullOrEmpty(mapping.GasSensorId))
                {
                    await this.m_client
                    .DeleteBucketsAsync(mapping.GasSensorId, DateTime.MinValue, lastProcessingTime, ct)
                    .ConfigureAwait(false);
                }

                if (!string.IsNullOrEmpty(mapping.EnvironmentSensorId))
                {
                    await this.m_client
                    .DeleteBucketsAsync(mapping.EnvironmentSensorId, DateTime.MinValue, lastProcessingTime, ct)
                    .ConfigureAwait(false);
                }
            }
        }