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); }
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); } } }