public StateEntity([NotNull] QboxState qboxState) { Guard.NotNull(qboxState, nameof(qboxState)); SerialNumber = qboxState.SerialNumber; RowKey = DateTimeRowKeyHelper.Construct(DateTime.UtcNow); CorrelationId = qboxState.CorrelationId; LogTimeStamp = qboxState.LogTime; MessageType = qboxState.MessageType; Message = qboxState.Message; State = qboxState.State; FirmwareVersion = qboxState.FirmwareVersion; MeterType = qboxState.MeterType; SequenceNumber = qboxState.SequenceNumber; Payloads = qboxState.Payloads; MessageTime = qboxState.MessageTime; // Copy all 'Last...' values var propertiesToCopy = typeof(QboxState).GetProperties() .Where(pi => pi.Name.StartsWith("Last") && (pi.PropertyType == typeof(string) || pi.PropertyType == typeof(DateTime) || pi.PropertyType == typeof(DateTime?)) ); foreach (var propertyInfo in propertiesToCopy) { var value = propertyInfo.GetValue(qboxState); var targetPropertyInfo = typeof(StateEntity).GetProperty(propertyInfo.Name); // Skip null values if (targetPropertyInfo != null && value != null) { targetPropertyInfo.SetValue(this, value); } } }
/// <inheritdoc cref="IAzureTablesService.StoreBatchAsync(IList{QboxMeasurement})"/> public async Task <bool> StoreBatchAsync(IList <QboxMeasurement> qboxMeasurements) { Guard.NotNull(qboxMeasurements, nameof(qboxMeasurements)); if (qboxMeasurements.Count == 0) { return(true); } var entities = (from entity in qboxMeasurements group entity by new { entity.SerialNumber, entity.MeasureTime, entity.MeasureTimeAdjusted } into g select new MeasurementEntity { PartitionKey = PartitionKeyHelper.Construct(g.Key.SerialNumber, g.Key.MeasureTime), RowKey = DateTimeRowKeyHelper.Construct(g.Key.MeasureTime), SerialNumber = g.Key.SerialNumber, MeasureTime = g.Key.MeasureTime, MeasureTimeAdjusted = g.Key.MeasureTimeAdjusted, CorrelationId = g.First().CorrelationId, Counter0181 = g.FirstOrDefault(c => c.CounterId == 181)?.PulseValue, Counter0182 = g.FirstOrDefault(c => c.CounterId == 182)?.PulseValue, Counter0281 = g.FirstOrDefault(c => c.CounterId == 281)?.PulseValue, Counter0282 = g.FirstOrDefault(c => c.CounterId == 282)?.PulseValue, Counter2421 = g.FirstOrDefault(c => c.CounterId == 2421)?.PulseValue }).ToList(); string serialNumber = qboxMeasurements.First().SerialNumber; string rowKey = entities.Count == 1 ? entities.First().RowKey : string.Empty; _logger.LogInformation("Inserting {Count} measurement(s) for '{SerialNumber}' with RowKey '{RowKey}' into Azure Table '{table}'", entities.Count, serialNumber, rowKey, _measurementTable.Name); return(await _measurementTable.Set.AddOrUpdateAsync(entities).TimeoutAfter(_serverTimeout) != null); }
/// <inheritdoc cref="IAzureTablesService.QueryDataAsync(string, DateTime, DateTime, QboxQueryResolution, bool)"/> public async Task <QboxPagedDataQueryResult <QboxCounterData> > QueryDataAsync(string serialNumber, DateTime from, DateTime to, QboxQueryResolution resolution, bool adjustHours) { Guard.NotNullOrEmpty(serialNumber, nameof(serialNumber)); int adjustedHours = 0; DateTime fromQueryParameter = from; if (adjustHours) { fromQueryParameter = from.AddDays(-1); adjustedHours = TimeZoneUtils.GetHoursDifferenceFromUTC(from); } string fromPartitionKey = PartitionKeyHelper.Construct(serialNumber, fromQueryParameter); string toPartitionKey = PartitionKeyHelper.Construct(serialNumber, to); string fromRowKey = DateTimeRowKeyHelper.Construct(fromQueryParameter); string toRowKey = DateTimeRowKeyHelper.Construct(to); _logger.LogInformation("Querying Table {table} with PartitionKey {fromPartitionKey} to {toPartitionKey} and RowKey {fromRowKey} to {toRowKey} and AdjustHours = {adjustHours}", _measurementTable.Name, fromPartitionKey, toPartitionKey, fromRowKey, toRowKey, adjustHours); var queue = new ConcurrentQueue <List <MeasurementEntity> >(); var tasks = EachDay(fromQueryParameter, to).Select(async date => { var result = await _measurementTable.Set.Where(m => m.PartitionKey == PartitionKeyHelper.Construct(serialNumber, date) && string.CompareOrdinal(m.RowKey, fromRowKey) <= 0 && string.CompareOrdinal(m.RowKey, toRowKey) > 0 ).ToListAsync(); queue.Enqueue(result); }); await Task.WhenAll(tasks); var entities = queue.SelectMany(x => x) .Where(e => e.MeasureTimeAdjusted != true) // Exclude adjusted measurements here. Not possible in real query above ! .Where(e => !adjustHours || e.MeasureTime > from.AddHours(-adjustedHours)) // Filter .OrderBy(e => e.MeasureTime).ToList(); // Adjust MeasureTime if needed if (adjustHours) { foreach (var entity in entities) { entity.MeasureTime = entity.MeasureTime.AddHours(adjustedHours); } } var deltas = entities.Zip(entities.Skip(1), (current, next) => new QboxCounterData { MeasureTime = next.MeasureTime, Delta0181 = next.Counter0181 - current.Counter0181 ?? 0, Delta0182 = next.Counter0182 - current.Counter0182 ?? 0, Delta0281 = next.Counter0281 - current.Counter0281 ?? 0, Delta0282 = next.Counter0282 - current.Counter0282 ?? 0, Delta2421 = next.Counter2421 - current.Counter2421 ?? 0, }).ToList(); if (deltas.Count > 0) { deltas.Insert(0, new QboxCounterData { MeasureTime = entities[0].MeasureTime, Delta0181 = 0, Delta0182 = 0, Delta0281 = 0, Delta0282 = 0, Delta2421 = 0 }); } var groupedByTimeFrame = from delta in deltas group delta by new { MeasureTimeRounded = resolution.TruncateTime(delta.MeasureTime) } into g select new QboxCounterData { LabelText = resolution.GetLabelText(g.Key.MeasureTimeRounded), LabelValue = resolution.GetLabelValue(g.Key.MeasureTimeRounded), MeasureTime = g.Key.MeasureTimeRounded, Delta0181 = g.Sum(x => x.Delta0181), Delta0182 = g.Sum(x => x.Delta0182), Delta0281 = g.Sum(x => x.Delta0281) * -1, Delta0282 = g.Sum(x => x.Delta0282) * -1, Delta2421 = g.Sum(x => x.Delta2421) }; var itemsFound = groupedByTimeFrame.ToList(); var items = FillGaps(from, to, resolution, itemsFound); var overview = new QboxCounterData { LabelText = "overview", MeasureTime = DateTime.UtcNow, Delta0181 = entities.Max(e => e.Counter0181) - entities.Min(e => e.Counter0181) ?? 0, Delta0182 = entities.Max(e => e.Counter0182) - entities.Min(e => e.Counter0182) ?? 0, Delta0281 = (entities.Max(e => e.Counter0281) - entities.Min(e => e.Counter0281) ?? 0) * -1, Delta0282 = (entities.Max(e => e.Counter0282) - entities.Min(e => e.Counter0282) ?? 0) * -1, Delta2421 = entities.Max(e => e.Counter2421) - entities.Min(e => e.Counter2421) ?? 0 }; // Define DrillDownQuery if (resolution > QboxQueryResolution.FiveMinutes) { foreach (var item in items) { item.DrillDownQuery = GetDrillDownQboxDataQuery(item.MeasureTime, resolution, adjustHours); } } return(new QboxPagedDataQueryResult <QboxCounterData> { Overview = overview, Items = items, Count = items.Count }); }