using Application.Domain.Entities; using Hangfire; using Hangfire.Storage; using Infrastructure.Application.Services.Settings; using Infrastructure.Data; using Infrastructure.Events; using Infrastructure.Extensions; using IoT.Shared.Application.Models; using Microsoft.AspNetCore.SignalR; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Logging; using System; using System.Linq; using System.Threading; namespace Platform.Services { public class ExecApiService : IExecApiService { private readonly IConfiguration _cfg; private readonly ILogger _logger; private readonly ISettingService _settingService; private readonly IRepository _sceneRepo; private readonly IRepository _organSceneCommandRepo; private readonly IRepository _organSceneTimerRepo; private readonly IRepository _commandRepo; private readonly IRepository _deviceRepo; private readonly IHubContext _hub; private readonly IEventPublisher _publisher; public ExecApiService(IConfiguration cfg, ILogger logger, ISettingService settingService, IRepository sceneRepo, IRepository organSceneCommandRepo, IRepository sceneTimerRepo, IRepository commandRepo, IRepository deviceRepo, IHubContext hub, IEventPublisher publisher) { this._cfg = cfg; this._logger = logger; this._settingService = settingService; this._sceneRepo = sceneRepo; this._organSceneCommandRepo = organSceneCommandRepo; this._organSceneTimerRepo = sceneTimerRepo; this._commandRepo = commandRepo; this._deviceRepo = deviceRepo; this._hub = hub; this._publisher = publisher; } public void UpdateTimer() { using var conn = JobStorage.Current.GetConnection(); var jobs = conn.GetRecurringJobs(); foreach (var job in jobs) { RecurringJob.RemoveIfExists(job.Id); } var list = this._organSceneTimerRepo.ReadOnlyTable().ToList(); foreach (var timer in list) { try { RecurringJob.AddOrUpdate(timer.Id.ToString(), () => TimerHandle(timer.Id), timer.Cron, TimeZoneInfo.Local); } catch (Exception ex) { ex.PrintStack(); this._logger.LogError(ex.ToString()); } } } public void TimerHandle(Guid id) { try { _logger.LogInformation($"global timer exec at {DateTime.Now:G}:{id}"); var scenes = _organSceneTimerRepo.ReadOnlyTable().Where(o => o.Id == id).Select(o => o.IoTScene.Id); foreach (var sceneId in scenes) { this.ExecScene(sceneId, null); } } catch (Exception ex) { _logger.LogError(ex.ToString()); } } public void ExecScene(Guid id, string connectionId) { var scene = this._sceneRepo.ReadOnlyTable() .Include(o => o.IoTSceneIoTCommands) .ThenInclude(o => o.IoTCommand.Api) .Include(o => o.IoTSceneIoTCommands) .ThenInclude(o => o.IoTCommand.IoTDevice.IoTGateway) .FirstOrDefault(o => o.Id == id); if (scene != null) { this._publisher.Publish(new BaseEvent(scene, nameof(ExecScene))); foreach (var item in scene.IoTSceneIoTCommands) { this.ExecCommandInternal(item.IoTCommand, connectionId); this.Delay(this._settingService, item.IoTCommand.Delay); } } } private void ExecCommandInternal(IoTCommand command, string connectionId) { var group = command.IoTDevice.IoTGateway.Number; var message = $"{command.Api.Path}{command.Api.Command}"; if (!string.IsNullOrEmpty(command.QueryString)) { message += "?" + command.QueryString; } this._hub.ServerToClient(Methods.ExecDeviceApi, message, group, connectionId); this._publisher.Publish(new BaseEvent(command, "ExecCommand")); } private void Delay(ISettingService _settingService, int delay) { if (int.TryParse(_settingService.GetValue("delay"), out int commandDelay)) { if (commandDelay > 0) { delay += commandDelay; } } if (delay > 0) { Thread.Sleep(delay); } } } }