first commit

This commit is contained in:
motahhari
2025-10-31 20:21:22 +03:30
commit 60d20a2734
186 changed files with 15497 additions and 0 deletions

View File

@@ -0,0 +1,134 @@
using System.Globalization;
using AutoMapper;
using GreenHome.Application;
using Microsoft.EntityFrameworkCore;
namespace GreenHome.Infrastructure;
public sealed class TelemetryService : ITelemetryService
{
private readonly GreenHomeDbContext dbContext;
private readonly IMapper mapper;
private static readonly PersianCalendar PersianCalendar = new PersianCalendar();
public TelemetryService(GreenHomeDbContext dbContext, IMapper mapper)
{
this.dbContext = dbContext;
this.mapper = mapper;
}
public async Task<int> AddAsync(TelemetryDto dto, CancellationToken cancellationToken)
{
var entity = mapper.Map<Domain.TelemetryRecord>(dto);
if (!string.IsNullOrEmpty(dto.DeviceName))
{
entity.DeviceId = dbContext.Devices.First(d => d.DeviceName == dto.DeviceName).Id;
}
var dt = dto.TimestampUtc;
var py = PersianCalendar.GetYear(dt);
var pm = PersianCalendar.GetMonth(dt);
var pd = PersianCalendar.GetDayOfMonth(dt);
entity.PersianYear = py;
entity.PersianMonth = pm;
entity.PersianDate = $"{py:0000}/{pm:00}/{pd:00}";
dbContext.TelemetryRecords.Add(entity);
await dbContext.SaveChangesAsync(cancellationToken);
return entity.Id;
}
public async Task<PagedResult<TelemetryDto>> ListAsync(TelemetryFilter filter, CancellationToken cancellationToken)
{
var query = dbContext.TelemetryRecords.AsNoTracking().AsQueryable();
if (filter.DeviceId.HasValue)
{
query = query.Where(x => x.DeviceId == filter.DeviceId.Value);
}
if (filter.StartDateUtc.HasValue)
{
var start = filter.StartDateUtc.Value.Date.AddDays(1);
query = query.Where(x => x.TimestampUtc >= start);
}
if (filter.EndDateUtc.HasValue)
{
var end = filter.EndDateUtc.Value.Date.AddDays(1);
query = query.Where(x => x.TimestampUtc < end);
}
var total = await query.CountAsync(cancellationToken);
var skip = (filter.Page - 1) * filter.PageSize;
var items = await query
.OrderByDescending(x => x.TimestampUtc)
.Skip(skip)
.Take(filter.PageSize)
.ToListAsync(cancellationToken);
return new PagedResult<TelemetryDto>
{
Items = mapper.Map<IReadOnlyList<TelemetryDto>>(items),
TotalCount = total,
Page = filter.Page,
PageSize = filter.PageSize
};
}
public async Task<TelemetryMinMax> GetMinMaxAsync(int deviceId, DateTime? startUtc, DateTime? endUtc, CancellationToken cancellationToken)
{
var query = dbContext.TelemetryRecords.AsNoTracking().Where(x => x.DeviceId == deviceId);
if (startUtc.HasValue) query = query.Where(x => x.TimestampUtc >= startUtc.Value);
if (endUtc.HasValue) query = query.Where(x => x.TimestampUtc <= endUtc.Value);
var result = await query
.Select(x => new
{
x.TemperatureC,
x.HumidityPercent,
x.SoilPercent,
x.GasPPM,
x.Lux
})
.ToListAsync(cancellationToken);
if (result.Count == 0)
{
return new TelemetryMinMax();
}
return new TelemetryMinMax
{
MinTemperatureC = result.Min(x => x.TemperatureC),
MaxTemperatureC = result.Max(x => x.TemperatureC),
MinHumidityPercent = result.Min(x => x.HumidityPercent),
MaxHumidityPercent = result.Max(x => x.HumidityPercent),
MinSoilPercent = result.Min(x => x.SoilPercent),
MaxSoilPercent = result.Max(x => x.SoilPercent),
MinGasPPM = result.Min(x => x.GasPPM),
MaxGasPPM = result.Max(x => x.GasPPM),
MinLux = result.Min(x => x.Lux),
MaxLux = result.Max(x => x.Lux)
};
}
public async Task<IReadOnlyList<DayCount>> GetMonthDaysAsync(int deviceId, int persianYear, int persianMonth, CancellationToken cancellationToken)
{
var query = dbContext.TelemetryRecords.AsNoTracking()
.Where(x => x.DeviceId == deviceId && x.PersianYear == persianYear && x.PersianMonth == persianMonth)
.GroupBy(x => x.PersianDate)
.Select(g => new DayCount { PersianDate = g.Key, Count = g.Count() })
.OrderBy(x => x.PersianDate);
return await query.ToListAsync(cancellationToken);
}
public async Task<IReadOnlyList<int>> GetActiveMonthsAsync(int deviceId, int persianYear, CancellationToken cancellationToken)
{
var months = await dbContext.TelemetryRecords.AsNoTracking()
.Where(x => x.DeviceId == deviceId && x.PersianYear == persianYear)
.Select(x => x.PersianMonth)
.Distinct()
.OrderBy(x => x)
.ToListAsync(cancellationToken);
return months;
}
}