version 2

This commit is contained in:
2025-12-16 16:52:40 +03:30
parent 61e86b1e96
commit 139924db94
52 changed files with 7350 additions and 321 deletions

View File

@@ -118,24 +118,88 @@ public sealed class DeviceSettingsDto
public int DeviceId { get; set; }
public string DeviceName { get; set; } = string.Empty;
// Temperature settings
public decimal DangerMaxTemperature { get; set; }
public decimal DangerMinTemperature { get; set; }
public decimal MaxTemperature { get; set; }
public decimal MinTemperature { get; set; }
// Gas settings
public int MaxGasPPM { get; set; }
public int MinGasPPM { get; set; }
// Light settings
public decimal MaxLux { get; set; }
public decimal MinLux { get; set; }
// Humidity settings
public decimal MaxHumidityPercent { get; set; }
public decimal MinHumidityPercent { get; set; }
public string Province { get; set; } = string.Empty;
public string City { get; set; } = string.Empty;
public decimal? Latitude { get; set; }
public decimal? Longitude { get; set; }
public DateTime CreatedAt { get; set; }
public DateTime UpdatedAt { get; set; }
}
public sealed class AlertConditionDto
{
public int Id { get; set; }
public int DeviceId { get; set; }
public string DeviceName { get; set; } = string.Empty;
public Domain.AlertNotificationType NotificationType { get; set; }
public Domain.AlertTimeType TimeType { get; set; }
public int CallCooldownMinutes { get; set; } = 60;
public int SmsCooldownMinutes { get; set; } = 15;
public bool IsEnabled { get; set; } = true;
public DateTime CreatedAt { get; set; }
public DateTime UpdatedAt { get; set; }
public List<AlertRuleDto> Rules { get; set; } = new();
}
public sealed class AlertRuleDto
{
public int Id { get; set; }
public int AlertConditionId { get; set; }
public Domain.SensorType SensorType { get; set; }
public Domain.ComparisonType ComparisonType { get; set; }
public decimal Value1 { get; set; }
public decimal? Value2 { get; set; }
public int Order { get; set; }
}
public sealed class CreateAlertConditionRequest
{
public required int DeviceId { get; set; }
public required Domain.AlertNotificationType NotificationType { get; set; }
public required Domain.AlertTimeType TimeType { get; set; }
public int CallCooldownMinutes { get; set; } = 60;
public int SmsCooldownMinutes { get; set; } = 15;
public bool IsEnabled { get; set; } = true;
public required List<CreateAlertRuleRequest> Rules { get; set; }
}
public sealed class CreateAlertRuleRequest
{
public required Domain.SensorType SensorType { get; set; }
public required Domain.ComparisonType ComparisonType { get; set; }
public required decimal Value1 { get; set; }
public decimal? Value2 { get; set; }
public int Order { get; set; }
}
public sealed class UpdateAlertConditionRequest
{
public required int Id { get; set; }
public required Domain.AlertNotificationType NotificationType { get; set; }
public required Domain.AlertTimeType TimeType { get; set; }
public int CallCooldownMinutes { get; set; } = 60;
public int SmsCooldownMinutes { get; set; } = 15;
public bool IsEnabled { get; set; } = true;
public required List<CreateAlertRuleRequest> Rules { get; set; }
}
public sealed class DailyReportRequest
{
public required int DeviceId { get; set; }
public required string PersianDate { get; set; } // yyyy/MM/dd
}
public sealed class DailyReportResponse
{
public int Id { get; set; }
public int DeviceId { get; set; }
public string DeviceName { get; set; } = string.Empty;
public string PersianDate { get; set; } = string.Empty;
public string Analysis { get; set; } = string.Empty;
public int RecordCount { get; set; }
public int SampledRecordCount { get; set; }
public int TotalTokens { get; set; }
public DateTime CreatedAt { get; set; }
public bool FromCache { get; set; }
}

View File

@@ -0,0 +1,59 @@
using GreenHome.Domain;
namespace GreenHome.Application;
/// <summary>
/// Service for managing AI queries and their history
/// </summary>
public interface IAIQueryService
{
/// <summary>
/// Saves an AI query to the database
/// </summary>
Task<AIQuery> SaveQueryAsync(AIQuery query, CancellationToken cancellationToken = default);
/// <summary>
/// Gets AI query history for a specific device
/// </summary>
Task<List<AIQuery>> GetDeviceQueriesAsync(int deviceId, int take = 50, CancellationToken cancellationToken = default);
/// <summary>
/// Gets AI query history for a specific user
/// </summary>
Task<List<AIQuery>> GetUserQueriesAsync(int userId, int take = 50, CancellationToken cancellationToken = default);
/// <summary>
/// Gets total token usage for a device
/// </summary>
Task<int> GetDeviceTotalTokensAsync(int deviceId, CancellationToken cancellationToken = default);
/// <summary>
/// Gets total token usage for a user
/// </summary>
Task<int> GetUserTotalTokensAsync(int userId, CancellationToken cancellationToken = default);
/// <summary>
/// Gets recent queries (all)
/// </summary>
Task<List<AIQuery>> GetRecentQueriesAsync(int take = 20, CancellationToken cancellationToken = default);
/// <summary>
/// Gets query statistics
/// </summary>
Task<AIQueryStats> GetStatsAsync(CancellationToken cancellationToken = default);
}
/// <summary>
/// Statistics about AI queries
/// </summary>
public class AIQueryStats
{
public int TotalQueries { get; set; }
public int TotalTokensUsed { get; set; }
public int TotalPromptTokens { get; set; }
public int TotalCompletionTokens { get; set; }
public double AverageResponseTimeMs { get; set; }
public int TodayQueries { get; set; }
public int TodayTokens { get; set; }
}

View File

@@ -0,0 +1,12 @@
namespace GreenHome.Application;
public interface IAlertConditionService
{
Task<IReadOnlyList<AlertConditionDto>> GetByDeviceIdAsync(int deviceId, CancellationToken cancellationToken);
Task<AlertConditionDto?> GetByIdAsync(int id, CancellationToken cancellationToken);
Task<int> CreateAsync(CreateAlertConditionRequest request, CancellationToken cancellationToken);
Task UpdateAsync(UpdateAlertConditionRequest request, CancellationToken cancellationToken);
Task DeleteAsync(int id, CancellationToken cancellationToken);
Task<bool> ToggleEnabledAsync(int id, bool isEnabled, CancellationToken cancellationToken);
}

View File

@@ -0,0 +1,13 @@
namespace GreenHome.Application;
public interface IDailyReportService
{
/// <summary>
/// Gets or generates a daily analysis report for a device on a specific date
/// </summary>
/// <param name="request">Request containing device ID and Persian date</param>
/// <param name="cancellationToken">Cancellation token</param>
/// <returns>Daily report with AI analysis</returns>
Task<DailyReportResponse> GetOrCreateDailyReportAsync(DailyReportRequest request, CancellationToken cancellationToken);
}

View File

@@ -0,0 +1,14 @@
namespace GreenHome.Application;
public interface ISunCalculatorService
{
/// <summary>
/// بررسی می‌کند که آیا زمان داده شده در روز است یا شب
/// </summary>
/// <param name="dateTime">زمان UTC</param>
/// <param name="latitude">عرض جغرافیایی</param>
/// <param name="longitude">طول جغرافیایی</param>
/// <returns>true اگر روز باشد، false اگر شب باشد</returns>
bool IsDaytime(DateTime dateTime, decimal latitude, decimal longitude);
}

View File

@@ -21,6 +21,16 @@ public sealed class MappingProfile : Profile
.ReverseMap()
.ForMember(dest => dest.Device, opt => opt.Ignore());
CreateMap<Domain.AlertCondition, AlertConditionDto>()
.ForMember(dest => dest.DeviceName, opt => opt.MapFrom(src => src.Device.DeviceName))
.ReverseMap()
.ForMember(dest => dest.Device, opt => opt.Ignore());
CreateMap<Domain.AlertRule, AlertRuleDto>().ReverseMap()
.ForMember(dest => dest.AlertCondition, opt => opt.Ignore());
CreateMap<CreateAlertRuleRequest, Domain.AlertRule>();
CreateMap<Domain.User, UserDto>().ReverseMap();
}
}