version 2
This commit is contained in:
358
src/GreenHome.Api/Controllers/AIController.cs
Normal file
358
src/GreenHome.Api/Controllers/AIController.cs
Normal file
@@ -0,0 +1,358 @@
|
||||
using GreenHome.AI.DeepSeek;
|
||||
using GreenHome.Application;
|
||||
using GreenHome.Domain;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace GreenHome.Api.Controllers;
|
||||
|
||||
[ApiController]
|
||||
[Route("api/[controller]")]
|
||||
public class AIController : ControllerBase
|
||||
{
|
||||
private readonly IDeepSeekService deepSeekService;
|
||||
private readonly IAIQueryService aiQueryService;
|
||||
private readonly ILogger<AIController> logger;
|
||||
|
||||
public AIController(
|
||||
IDeepSeekService deepSeekService,
|
||||
IAIQueryService aiQueryService,
|
||||
ILogger<AIController> logger)
|
||||
{
|
||||
this.deepSeekService = deepSeekService;
|
||||
this.aiQueryService = aiQueryService;
|
||||
this.logger = logger;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Send a simple question to the AI and get a response
|
||||
/// </summary>
|
||||
/// <param name="request">Question request</param>
|
||||
/// <returns>AI response</returns>
|
||||
[HttpPost("ask")]
|
||||
public async Task<IActionResult> AskQuestion([FromBody] SimpleQuestionRequest request)
|
||||
{
|
||||
var stopwatch = Stopwatch.StartNew();
|
||||
|
||||
try
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(request.Question))
|
||||
{
|
||||
return BadRequest(new { error = "Question is required" });
|
||||
}
|
||||
|
||||
logger.LogInformation("Processing AI question: {Question}", request.Question);
|
||||
|
||||
// Build chat request to get token information
|
||||
var messages = new List<ChatMessage>();
|
||||
if (!string.IsNullOrWhiteSpace(request.SystemPrompt))
|
||||
{
|
||||
messages.Add(new ChatMessage { Role = "system", Content = request.SystemPrompt });
|
||||
}
|
||||
messages.Add(new ChatMessage { Role = "user", Content = request.Question });
|
||||
|
||||
var chatRequest = new ChatRequest { Messages = messages };
|
||||
var chatResponse = await deepSeekService.AskAsync(chatRequest);
|
||||
|
||||
stopwatch.Stop();
|
||||
|
||||
if (chatResponse == null || chatResponse.Choices == null || !chatResponse.Choices.Any())
|
||||
{
|
||||
return StatusCode(500, new { error = "No response received from AI" });
|
||||
}
|
||||
|
||||
var answer = chatResponse.Choices.FirstOrDefault()?.Message?.Content ?? "";
|
||||
|
||||
// Save to database
|
||||
var aiQuery = new AIQuery
|
||||
{
|
||||
Question = request.Question,
|
||||
Answer = answer,
|
||||
DeviceId = request.DeviceId,
|
||||
UserId = request.UserId,
|
||||
Model = chatResponse.Model,
|
||||
PromptTokens = chatResponse.Usage?.PromptTokens ?? 0,
|
||||
CompletionTokens = chatResponse.Usage?.CompletionTokens ?? 0,
|
||||
TotalTokens = chatResponse.Usage?.TotalTokens ?? 0,
|
||||
ResponseTimeMs = stopwatch.ElapsedMilliseconds
|
||||
};
|
||||
|
||||
await aiQueryService.SaveQueryAsync(aiQuery);
|
||||
|
||||
return Ok(new
|
||||
{
|
||||
question = request.Question,
|
||||
answer = answer,
|
||||
deviceId = request.DeviceId,
|
||||
tokens = new
|
||||
{
|
||||
prompt = aiQuery.PromptTokens,
|
||||
completion = aiQuery.CompletionTokens,
|
||||
total = aiQuery.TotalTokens
|
||||
},
|
||||
responseTimeMs = aiQuery.ResponseTimeMs,
|
||||
timestamp = DateTime.UtcNow
|
||||
});
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
logger.LogError(ex, "Error processing AI question");
|
||||
return StatusCode(500, new { error = "An error occurred while processing your question" });
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Send a complex chat request with multiple messages to the AI
|
||||
/// </summary>
|
||||
/// <param name="request">Extended chat request with deviceId</param>
|
||||
/// <returns>AI chat response</returns>
|
||||
[HttpPost("chat")]
|
||||
public async Task<IActionResult> Chat([FromBody] ExtendedChatRequest request)
|
||||
{
|
||||
var stopwatch = Stopwatch.StartNew();
|
||||
|
||||
try
|
||||
{
|
||||
if (request.Messages == null || !request.Messages.Any())
|
||||
{
|
||||
return BadRequest(new { error = "At least one message is required" });
|
||||
}
|
||||
|
||||
logger.LogInformation("Processing AI chat with {MessageCount} messages", request.Messages.Count);
|
||||
|
||||
var chatRequest = new ChatRequest
|
||||
{
|
||||
Messages = request.Messages,
|
||||
Model = request.Model,
|
||||
Temperature = request.Temperature,
|
||||
MaxTokens = request.MaxTokens
|
||||
};
|
||||
|
||||
var response = await deepSeekService.AskAsync(chatRequest);
|
||||
|
||||
stopwatch.Stop();
|
||||
|
||||
if (response == null || response.Choices == null || !response.Choices.Any())
|
||||
{
|
||||
return StatusCode(500, new { error = "No response received from AI" });
|
||||
}
|
||||
|
||||
// Extract question and answer
|
||||
var userMessage = request.Messages.LastOrDefault(m => m.Role == "user");
|
||||
var question = userMessage?.Content ?? "Complex chat";
|
||||
var answer = response.Choices.FirstOrDefault()?.Message?.Content ?? "";
|
||||
|
||||
// Save to database
|
||||
var aiQuery = new AIQuery
|
||||
{
|
||||
Question = question,
|
||||
Answer = answer,
|
||||
DeviceId = request.DeviceId,
|
||||
UserId = request.UserId,
|
||||
Model = response.Model,
|
||||
Temperature = request.Temperature,
|
||||
PromptTokens = response.Usage?.PromptTokens ?? 0,
|
||||
CompletionTokens = response.Usage?.CompletionTokens ?? 0,
|
||||
TotalTokens = response.Usage?.TotalTokens ?? 0,
|
||||
ResponseTimeMs = stopwatch.ElapsedMilliseconds
|
||||
};
|
||||
|
||||
await aiQueryService.SaveQueryAsync(aiQuery);
|
||||
|
||||
return Ok(response);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
logger.LogError(ex, "Error processing AI chat");
|
||||
return StatusCode(500, new { error = "An error occurred while processing your chat request" });
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get suggestions for smart home automation based on device data
|
||||
/// </summary>
|
||||
/// <param name="request">Device context request</param>
|
||||
/// <returns>AI suggestions</returns>
|
||||
[HttpPost("suggest")]
|
||||
public async Task<IActionResult> GetSuggestions([FromBody] SuggestionRequest request)
|
||||
{
|
||||
var stopwatch = Stopwatch.StartNew();
|
||||
|
||||
try
|
||||
{
|
||||
var systemPrompt = @"شما یک مشاور هوشمند خانه هوشمند هستید. بر اساس دادههای دستگاههای IoT، پیشنهادهای عملی و مفید برای بهینهسازی مصرف انرژی، راحتی و امنیت ارائه دهید. پاسخ را به زبان فارسی و به صورت خلاصه و کاربردی بنویسید.";
|
||||
|
||||
var question = $@"وضعیت فعلی دستگاههای خانه هوشمند:
|
||||
{request.DeviceContext}
|
||||
|
||||
لطفاً پیشنهادات خود را برای بهبود وضعیت ارائه دهید.";
|
||||
|
||||
var messages = new List<ChatMessage>
|
||||
{
|
||||
new ChatMessage { Role = "system", Content = systemPrompt },
|
||||
new ChatMessage { Role = "user", Content = question }
|
||||
};
|
||||
|
||||
var chatRequest = new ChatRequest { Messages = messages };
|
||||
var chatResponse = await deepSeekService.AskAsync(chatRequest);
|
||||
|
||||
stopwatch.Stop();
|
||||
|
||||
if (chatResponse == null || chatResponse.Choices == null || !chatResponse.Choices.Any())
|
||||
{
|
||||
return StatusCode(500, new { error = "No suggestions received from AI" });
|
||||
}
|
||||
|
||||
var answer = chatResponse.Choices.FirstOrDefault()?.Message?.Content ?? "";
|
||||
|
||||
// Save to database
|
||||
var aiQuery = new AIQuery
|
||||
{
|
||||
Question = question,
|
||||
Answer = answer,
|
||||
DeviceId = request.DeviceId,
|
||||
UserId = request.UserId,
|
||||
Model = chatResponse.Model,
|
||||
PromptTokens = chatResponse.Usage?.PromptTokens ?? 0,
|
||||
CompletionTokens = chatResponse.Usage?.CompletionTokens ?? 0,
|
||||
TotalTokens = chatResponse.Usage?.TotalTokens ?? 0,
|
||||
ResponseTimeMs = stopwatch.ElapsedMilliseconds
|
||||
};
|
||||
|
||||
await aiQueryService.SaveQueryAsync(aiQuery);
|
||||
|
||||
return Ok(new
|
||||
{
|
||||
suggestions = answer,
|
||||
deviceId = request.DeviceId,
|
||||
tokens = new
|
||||
{
|
||||
prompt = aiQuery.PromptTokens,
|
||||
completion = aiQuery.CompletionTokens,
|
||||
total = aiQuery.TotalTokens
|
||||
},
|
||||
responseTimeMs = aiQuery.ResponseTimeMs,
|
||||
timestamp = DateTime.UtcNow
|
||||
});
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
logger.LogError(ex, "Error getting AI suggestions");
|
||||
return StatusCode(500, new { error = "An error occurred while getting suggestions" });
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get AI query history for a device
|
||||
/// </summary>
|
||||
[HttpGet("history/device/{deviceId}")]
|
||||
public async Task<IActionResult> GetDeviceHistory(int deviceId, [FromQuery] int take = 50)
|
||||
{
|
||||
try
|
||||
{
|
||||
var queries = await aiQueryService.GetDeviceQueriesAsync(deviceId, take);
|
||||
var totalTokens = await aiQueryService.GetDeviceTotalTokensAsync(deviceId);
|
||||
|
||||
return Ok(new
|
||||
{
|
||||
queries = queries.Select(q => new
|
||||
{
|
||||
q.Id,
|
||||
q.Question,
|
||||
q.Answer,
|
||||
q.TotalTokens,
|
||||
q.PromptTokens,
|
||||
q.CompletionTokens,
|
||||
q.Model,
|
||||
q.ResponseTimeMs,
|
||||
q.CreatedAt
|
||||
}),
|
||||
totalTokens
|
||||
});
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
logger.LogError(ex, "Error getting device history");
|
||||
return StatusCode(500, new { error = "An error occurred" });
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get AI query statistics
|
||||
/// </summary>
|
||||
[HttpGet("stats")]
|
||||
public async Task<IActionResult> GetStats()
|
||||
{
|
||||
try
|
||||
{
|
||||
var stats = await aiQueryService.GetStatsAsync();
|
||||
return Ok(stats);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
logger.LogError(ex, "Error getting stats");
|
||||
return StatusCode(500, new { error = "An error occurred" });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Simple question request model
|
||||
/// </summary>
|
||||
public class SimpleQuestionRequest
|
||||
{
|
||||
/// <summary>
|
||||
/// The question to ask the AI
|
||||
/// </summary>
|
||||
public required string Question { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Optional system prompt to set context for the AI
|
||||
/// </summary>
|
||||
public string? SystemPrompt { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Optional device ID to associate with this query
|
||||
/// </summary>
|
||||
public int? DeviceId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Optional user ID to associate with this query
|
||||
/// </summary>
|
||||
public int? UserId { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Extended chat request with device tracking
|
||||
/// </summary>
|
||||
public class ExtendedChatRequest
|
||||
{
|
||||
public required List<ChatMessage> Messages { get; set; }
|
||||
public string Model { get; set; } = "deepseek-chat";
|
||||
public double? Temperature { get; set; }
|
||||
public int? MaxTokens { get; set; }
|
||||
public int? DeviceId { get; set; }
|
||||
public int? UserId { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Suggestion request for smart home automation
|
||||
/// </summary>
|
||||
public class SuggestionRequest
|
||||
{
|
||||
/// <summary>
|
||||
/// Context about devices and their current state
|
||||
/// </summary>
|
||||
public required string DeviceContext { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Device ID for this suggestion request
|
||||
/// </summary>
|
||||
public int? DeviceId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// User ID for this suggestion request
|
||||
/// </summary>
|
||||
public int? UserId { get; set; }
|
||||
}
|
||||
|
||||
85
src/GreenHome.Api/Controllers/AlertConditionsController.cs
Normal file
85
src/GreenHome.Api/Controllers/AlertConditionsController.cs
Normal file
@@ -0,0 +1,85 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using GreenHome.Application;
|
||||
|
||||
namespace GreenHome.Api.Controllers;
|
||||
|
||||
[ApiController]
|
||||
[Route("api/[controller]")]
|
||||
public class AlertConditionsController : ControllerBase
|
||||
{
|
||||
private readonly IAlertConditionService alertConditionService;
|
||||
|
||||
public AlertConditionsController(IAlertConditionService alertConditionService)
|
||||
{
|
||||
this.alertConditionService = alertConditionService;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// دریافت تمام شرایط هشدار یک دستگاه
|
||||
/// </summary>
|
||||
[HttpGet("device/{deviceId}")]
|
||||
public async Task<ActionResult<IReadOnlyList<AlertConditionDto>>> GetByDeviceId(int deviceId, CancellationToken cancellationToken)
|
||||
{
|
||||
var result = await alertConditionService.GetByDeviceIdAsync(deviceId, cancellationToken);
|
||||
return Ok(result);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// دریافت یک شرط هشدار با ID
|
||||
/// </summary>
|
||||
[HttpGet("{id}")]
|
||||
public async Task<ActionResult<AlertConditionDto>> GetById(int id, CancellationToken cancellationToken)
|
||||
{
|
||||
var result = await alertConditionService.GetByIdAsync(id, cancellationToken);
|
||||
if (result == null)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
return Ok(result);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// ایجاد شرط هشدار جدید
|
||||
/// </summary>
|
||||
[HttpPost]
|
||||
public async Task<ActionResult<int>> Create(CreateAlertConditionRequest request, CancellationToken cancellationToken)
|
||||
{
|
||||
var id = await alertConditionService.CreateAsync(request, cancellationToken);
|
||||
return Ok(id);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// بهروزرسانی شرط هشدار
|
||||
/// </summary>
|
||||
[HttpPut]
|
||||
public async Task<ActionResult> Update(UpdateAlertConditionRequest request, CancellationToken cancellationToken)
|
||||
{
|
||||
await alertConditionService.UpdateAsync(request, cancellationToken);
|
||||
return Ok();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// حذف شرط هشدار
|
||||
/// </summary>
|
||||
[HttpDelete("{id}")]
|
||||
public async Task<ActionResult> Delete(int id, CancellationToken cancellationToken)
|
||||
{
|
||||
await alertConditionService.DeleteAsync(id, cancellationToken);
|
||||
return Ok();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// فعال/غیرفعال کردن شرط هشدار
|
||||
/// </summary>
|
||||
[HttpPatch("{id}/toggle")]
|
||||
public async Task<ActionResult> ToggleEnabled(int id, [FromBody] bool isEnabled, CancellationToken cancellationToken)
|
||||
{
|
||||
var result = await alertConditionService.ToggleEnabledAsync(id, isEnabled, cancellationToken);
|
||||
if (!result)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
return Ok();
|
||||
}
|
||||
}
|
||||
|
||||
77
src/GreenHome.Api/Controllers/DailyReportController.cs
Normal file
77
src/GreenHome.Api/Controllers/DailyReportController.cs
Normal file
@@ -0,0 +1,77 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using GreenHome.Application;
|
||||
|
||||
namespace GreenHome.Api.Controllers;
|
||||
|
||||
[ApiController]
|
||||
[Route("api/[controller]")]
|
||||
public class DailyReportController : ControllerBase
|
||||
{
|
||||
private readonly IDailyReportService _dailyReportService;
|
||||
private readonly ILogger<DailyReportController> _logger;
|
||||
|
||||
public DailyReportController(
|
||||
IDailyReportService dailyReportService,
|
||||
ILogger<DailyReportController> logger)
|
||||
{
|
||||
_dailyReportService = dailyReportService;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// دریافت یا ایجاد گزارش تحلیل روزانه گلخانه
|
||||
/// </summary>
|
||||
/// <param name="deviceId">شناسه دستگاه</param>
|
||||
/// <param name="persianDate">تاریخ شمسی به فرمت yyyy/MM/dd</param>
|
||||
/// <param name="cancellationToken">Cancellation token</param>
|
||||
/// <returns>گزارش تحلیل روزانه</returns>
|
||||
[HttpGet]
|
||||
public async Task<ActionResult<DailyReportResponse>> GetDailyReport(
|
||||
[FromQuery] int deviceId,
|
||||
[FromQuery] string persianDate,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (deviceId <= 0)
|
||||
{
|
||||
return BadRequest(new { error = "شناسه دستگاه نامعتبر است" });
|
||||
}
|
||||
|
||||
if (string.IsNullOrWhiteSpace(persianDate))
|
||||
{
|
||||
return BadRequest(new { error = "تاریخ نباید خالی باشد" });
|
||||
}
|
||||
|
||||
var request = new DailyReportRequest
|
||||
{
|
||||
DeviceId = deviceId,
|
||||
PersianDate = persianDate.Trim()
|
||||
};
|
||||
|
||||
var result = await _dailyReportService.GetOrCreateDailyReportAsync(request, cancellationToken);
|
||||
|
||||
_logger.LogInformation(
|
||||
"گزارش روزانه برای دستگاه {DeviceId} و تاریخ {Date} با موفقیت برگشت داده شد (FromCache: {FromCache})",
|
||||
deviceId, persianDate, result.FromCache);
|
||||
|
||||
return Ok(result);
|
||||
}
|
||||
catch (ArgumentException ex)
|
||||
{
|
||||
_logger.LogWarning(ex, "درخواست نامعتبر برای دستگاه {DeviceId} و تاریخ {Date}", deviceId, persianDate);
|
||||
return BadRequest(new { error = ex.Message });
|
||||
}
|
||||
catch (InvalidOperationException ex)
|
||||
{
|
||||
_logger.LogWarning(ex, "خطا در پردازش گزارش روزانه برای دستگاه {DeviceId} و تاریخ {Date}", deviceId, persianDate);
|
||||
return NotFound(new { error = ex.Message });
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "خطای سرور در دریافت گزارش روزانه برای دستگاه {DeviceId} و تاریخ {Date}", deviceId, persianDate);
|
||||
return StatusCode(500, new { error = "خطای سرور در پردازش درخواست" });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
<ProjectReference Include="..\GreenHome.Infrastructure\GreenHome.Infrastructure.csproj" />
|
||||
<ProjectReference Include="..\GreenHome.Sms.Ippanel\GreenHome.Sms.Ippanel.csproj" />
|
||||
<ProjectReference Include="..\GreenHome.VoiceCall.Avanak\GreenHome.VoiceCall.Avanak.csproj" />
|
||||
<ProjectReference Include="..\GreenHome.AI.DeepSeek\GreenHome.AI.DeepSeek.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using FluentValidation;
|
||||
using GreenHome.AI.DeepSeek;
|
||||
using GreenHome.Application;
|
||||
using GreenHome.Infrastructure;
|
||||
using GreenHome.Sms.Ippanel;
|
||||
@@ -15,26 +16,35 @@ builder.Services.AddSwaggerGen();
|
||||
builder.Services.AddAutoMapper(typeof(GreenHome.Application.MappingProfile));
|
||||
builder.Services.AddValidatorsFromAssemblyContaining<GreenHome.Application.DeviceDtoValidator>();
|
||||
|
||||
// CORS for Next.js dev (adjust origins as needed)
|
||||
// CORS Configuration
|
||||
const string CorsPolicy = "DefaultCors";
|
||||
builder.Services.AddCors(options =>
|
||||
{
|
||||
options.AddPolicy(CorsPolicy, policy =>
|
||||
policy
|
||||
.WithOrigins(
|
||||
"http://green.nabaksoft.ir",
|
||||
"https://green.nabaksoft.ir",
|
||||
"http://gh1.nabaksoft.ir",
|
||||
"https://gh1.nabaksoft.ir",
|
||||
"http://localhost:3000",
|
||||
"http://localhost:3000",
|
||||
"http://127.0.0.1:3000",
|
||||
"https://localhost:3000"
|
||||
)
|
||||
.AllowAnyHeader()
|
||||
.AllowAnyMethod()
|
||||
.AllowCredentials()
|
||||
);
|
||||
{
|
||||
if (builder.Environment.IsDevelopment())
|
||||
{
|
||||
// در محیط Development همه origin ها مجاز هستند
|
||||
policy
|
||||
.AllowAnyOrigin()
|
||||
.AllowAnyHeader()
|
||||
.AllowAnyMethod();
|
||||
}
|
||||
else
|
||||
{
|
||||
// در محیط Production فقط دامنههای مشخص
|
||||
policy
|
||||
.WithOrigins(
|
||||
"http://green.nabaksoft.ir",
|
||||
"https://green.nabaksoft.ir",
|
||||
"http://gh1.nabaksoft.ir",
|
||||
"https://gh1.nabaksoft.ir"
|
||||
)
|
||||
.AllowAnyHeader()
|
||||
.AllowAnyMethod()
|
||||
.AllowCredentials();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
builder.Services.AddDbContext<GreenHome.Infrastructure.GreenHomeDbContext>(options =>
|
||||
@@ -46,6 +56,10 @@ builder.Services.AddScoped<GreenHome.Application.ITelemetryService, GreenHome.In
|
||||
builder.Services.AddScoped<GreenHome.Application.IDeviceSettingsService, GreenHome.Infrastructure.DeviceSettingsService>();
|
||||
builder.Services.AddScoped<GreenHome.Application.IAuthService, GreenHome.Infrastructure.AuthService>();
|
||||
builder.Services.AddScoped<GreenHome.Application.IAlertService, GreenHome.Infrastructure.AlertService>();
|
||||
builder.Services.AddScoped<GreenHome.Application.IAlertConditionService, GreenHome.Infrastructure.AlertConditionService>();
|
||||
builder.Services.AddScoped<GreenHome.Application.ISunCalculatorService, GreenHome.Infrastructure.SunCalculatorService>();
|
||||
builder.Services.AddScoped<GreenHome.Application.IAIQueryService, GreenHome.Infrastructure.AIQueryService>();
|
||||
builder.Services.AddScoped<GreenHome.Application.IDailyReportService, GreenHome.Infrastructure.DailyReportService>();
|
||||
|
||||
// SMS Service Configuration
|
||||
builder.Services.AddIppanelSms(builder.Configuration);
|
||||
@@ -53,6 +67,9 @@ builder.Services.AddIppanelSms(builder.Configuration);
|
||||
// Voice Call Service Configuration
|
||||
builder.Services.AddAvanakVoiceCall(builder.Configuration);
|
||||
|
||||
// AI Service Configuration
|
||||
builder.Services.AddDeepSeek(builder.Configuration);
|
||||
|
||||
var app = builder.Build();
|
||||
|
||||
// Apply pending migrations automatically
|
||||
@@ -78,7 +95,11 @@ using (var scope = app.Services.CreateScope())
|
||||
app.UseSwaggerUI();
|
||||
}
|
||||
|
||||
app.UseHttpsRedirection();
|
||||
// HTTPS Redirection فقط در Production
|
||||
if (!app.Environment.IsDevelopment())
|
||||
{
|
||||
app.UseHttpsRedirection();
|
||||
}
|
||||
|
||||
app.UseCors(CorsPolicy);
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
},
|
||||
"dotnetRunMessages": true,
|
||||
"applicationUrl": "http://localhost:5064"
|
||||
"applicationUrl": "http://0.0.0.0:5064"
|
||||
},
|
||||
"https": {
|
||||
"commandName": "Project",
|
||||
@@ -14,7 +14,7 @@
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
},
|
||||
"dotnetRunMessages": true,
|
||||
"applicationUrl": "https://localhost:7274;http://localhost:5064"
|
||||
"applicationUrl": "https://0.0.0.0:7274;http://0.0.0.0:5064"
|
||||
},
|
||||
"IIS Express": {
|
||||
"commandName": "IISExpress",
|
||||
|
||||
@@ -4,5 +4,16 @@
|
||||
"Default": "Information",
|
||||
"Microsoft.AspNetCore": "Warning"
|
||||
}
|
||||
},
|
||||
"ConnectionStrings": {
|
||||
"Default": "Server=87.107.108.119;TrustServerCertificate=True;Database=GreenHomeDb;User Id=sa;Password=qwER12#$110"
|
||||
},
|
||||
"AvanakVoiceCall": {
|
||||
"Token": "A948B776B90CFD919B0EC60929714136CCB49DDB"
|
||||
},
|
||||
"IppanelSms": {
|
||||
"BaseUrl": "https://edge.ippanel.com/v1",
|
||||
"AuthorizationToken": "YTA1Zjk3N2EtNzkwOC00ZTg5LWFjZmYtZGEyZDAyNjNlZWQxM2Q2ZDVjYWE0MTA2Yzc1NDYzZDY1Y2VkMjlhMzcwNjA=",
|
||||
"DefaultSender": "+983000505"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -11,5 +11,12 @@
|
||||
"AuthorizationToken": "YTA1Zjk3N2EtNzkwOC00ZTg5LWFjZmYtZGEyZDAyNjNlZWQxM2Q2ZDVjYWE0MTA2Yzc1NDYzZDY1Y2VkMjlhMzcwNjA=",
|
||||
"DefaultSender": "+983000505"
|
||||
},
|
||||
"DeepSeek": {
|
||||
"BaseUrl": "https://api.deepseek.com",
|
||||
"ApiKey": "sk-4470fc1a003a445e92f357dbe123e5a4",
|
||||
"DefaultModel": "deepseek-chat",
|
||||
"DefaultTemperature": 1.0
|
||||
},
|
||||
|
||||
"AllowedHosts": "*"
|
||||
}
|
||||
Reference in New Issue
Block a user