111111
This commit is contained in:
@@ -46,6 +46,14 @@ public sealed class HomeAssistantEntityOptions
|
||||
public string FragranceDuration { get; set; } = string.Empty;
|
||||
public string FragranceInterval { get; set; } = string.Empty;
|
||||
public string FragranceQuickRelease { get; set; } = string.Empty;
|
||||
public string WakeFragranceSwitch { get; set; } = string.Empty;
|
||||
public string WakeFragranceLight { get; set; } = string.Empty;
|
||||
public string WakeFragranceDuration { get; set; } = string.Empty;
|
||||
public string WakeFragranceInterval { get; set; } = string.Empty;
|
||||
public string WakeFragranceQuickRelease { get; set; } = string.Empty;
|
||||
public string WakeFragranceAutoRelease { get; set; } = string.Empty;
|
||||
public string WakeFragranceAutoLight { get; set; } = string.Empty;
|
||||
public string WakeFragranceLightAutoOff { get; set; } = string.Empty;
|
||||
public string FragranceAutoRelease { get; set; } = string.Empty;
|
||||
public string FragranceAutoLight { get; set; } = string.Empty;
|
||||
public string FragranceLightAutoOff { get; set; } = string.Empty;
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
using Evergreen.Health.Application.Health.Sleep;
|
||||
|
||||
namespace Evergreen.Health.Application.Health.Integrations.Ib43;
|
||||
|
||||
public sealed class Ib43AutomationExecutionLog(IServiceScopeFactory scopes) : IBedPresenceExecutionLog
|
||||
{
|
||||
public async Task<string?> BeginAsync(string bindingId, long userId, string action, string target,
|
||||
DateTimeOffset triggeredAt, CancellationToken token)
|
||||
{
|
||||
using var scope = scopes.CreateScope();
|
||||
return await scope.ServiceProvider.GetRequiredService<Ib43DataRepository>()
|
||||
.BeginAutomation(bindingId, userId, action, target, triggeredAt.ToUnixTimeMilliseconds(), token);
|
||||
}
|
||||
|
||||
public async Task CompleteAsync(string id, string result, DateTimeOffset completedAt)
|
||||
{
|
||||
using var scope = scopes.CreateScope();
|
||||
await scope.ServiceProvider.GetRequiredService<Ib43DataRepository>()
|
||||
.CompleteAutomation(id, result, completedAt.ToUnixTimeMilliseconds());
|
||||
}
|
||||
}
|
||||
@@ -31,6 +31,26 @@ public sealed class Ib43DataRepository(ISqlSugarClient db)
|
||||
await db.Queryable<HealthIb43Binding>().Where(b => b.Id == id && b.UserId == userId).FirstAsync()
|
||||
?? throw new AppFriendlyException("床位绑定不存在或无权访问", null) { StatusCode = 404 };
|
||||
|
||||
public Task<List<HealthIb43AutomationExecution>> AutomationHistory(long userId, string bindingId) =>
|
||||
db.Queryable<HealthIb43AutomationExecution>().Where(row => row.UserId == userId && row.BindingId == bindingId)
|
||||
.OrderBy(row => row.TriggeredAtMs, OrderByType.Desc).Take(20).ToListAsync();
|
||||
|
||||
public async Task<string?> BeginAutomation(string bindingId, long userId, string action, string target, long triggeredAtMs, CancellationToken token)
|
||||
{
|
||||
token.ThrowIfCancellationRequested();
|
||||
if (!await UserEnabled(userId) || !await db.Queryable<HealthIb43Binding>().AnyAsync(b => b.Id == bindingId &&
|
||||
b.UserId == userId && b.Simulation && b.EndedAtMs == null && b.StartedAtMs <= triggeredAtMs)) return null;
|
||||
var record = new HealthIb43AutomationExecution
|
||||
{ BindingId = bindingId, UserId = userId, ActionKey = action, TargetLabel = target, TriggeredAtMs = triggeredAtMs };
|
||||
token.ThrowIfCancellationRequested();
|
||||
await db.Insertable(record).ExecuteCommandAsync();
|
||||
return record.Id;
|
||||
}
|
||||
|
||||
public Task<int> CompleteAutomation(string id, string result, long completedAtMs) => db.Updateable<HealthIb43AutomationExecution>()
|
||||
.SetColumns(row => new HealthIb43AutomationExecution { Result = result, CompletedAtMs = completedAtMs })
|
||||
.Where(row => row.Id == id && row.CompletedAtMs == null).ExecuteCommandAsync();
|
||||
|
||||
public async Task Assign(HealthIb43Binding binding)
|
||||
{
|
||||
if (await db.Queryable<HealthIb43Binding>().AnyAsync(b => b.ActiveSlot == binding.ActiveSlot))
|
||||
|
||||
+9
-1
@@ -61,7 +61,13 @@ public sealed class TcmMusicTransitionService : IHostedService, ITcmMusicRuntime
|
||||
tracks is not null && tracks.Count > 0 &&
|
||||
tracks.All(track => IsValidTrack(track));
|
||||
|
||||
public async Task StartForConstitutionAsync(string constitutionCode, CancellationToken cancellationToken)
|
||||
public Task StartForConstitutionAsync(string constitutionCode, CancellationToken cancellationToken) =>
|
||||
StartAsync(constitutionCode, onlyIfIdle: false, cancellationToken);
|
||||
|
||||
internal Task<bool> TryStartIdlePlaybackAsync(string constitutionCode, CancellationToken cancellationToken) =>
|
||||
StartAsync(constitutionCode, onlyIfIdle: true, cancellationToken);
|
||||
|
||||
private async Task<bool> StartAsync(string constitutionCode, bool onlyIfIdle, CancellationToken cancellationToken)
|
||||
{
|
||||
if (!HasPlayableTracks(constitutionCode))
|
||||
throw new InvalidOperationException($"{constitutionCode} 的体质音乐 OSS URL 尚未配置完整");
|
||||
@@ -69,12 +75,14 @@ public sealed class TcmMusicTransitionService : IHostedService, ITcmMusicRuntime
|
||||
await _operationLock.WaitAsync(cancellationToken);
|
||||
try
|
||||
{
|
||||
if (onlyIfIdle && _activeTask is { IsCompleted: false }) return false;
|
||||
await CancelCurrentLoopAsync();
|
||||
await _miAirX.SetVolumeAsync(DemoStartVolume, cancellationToken);
|
||||
await _miAirX.PlayUrlAsync(tracks[0].Url, cancellationToken);
|
||||
UpdateStatus(true, DemoStartVolume, "体质音乐正在自动渐弱");
|
||||
_activeCancellation = new CancellationTokenSource();
|
||||
_activeTask = RunFadeAsync(tracks, constitutionCode, _activeCancellation.Token);
|
||||
return true;
|
||||
}
|
||||
finally { _operationLock.Release(); }
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user