111111
This commit is contained in:
@@ -25,13 +25,22 @@ public sealed class DeviceActionRunner
|
||||
public async Task<HomeAssistantState> ReadAvailableStateAsync(string entityId, CancellationToken cancellationToken)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(entityId)) throw new InvalidOperationException("参数实体尚未配置");
|
||||
var state = (await _gateway.GetStatesAsync(cancellationToken)).FirstOrDefault(item =>
|
||||
return RequireAvailableState(await _gateway.GetStatesAsync(cancellationToken), entityId);
|
||||
}
|
||||
|
||||
private static HomeAssistantState RequireAvailableState(IReadOnlyList<HomeAssistantState> states, string entityId)
|
||||
{
|
||||
var state = states.FirstOrDefault(item =>
|
||||
string.Equals(item.EntityId, entityId, StringComparison.OrdinalIgnoreCase));
|
||||
if (state is null || !IsAvailable(state)) throw new InvalidOperationException("目标参数实体当前离线或不可用");
|
||||
return state;
|
||||
}
|
||||
|
||||
public async Task SendAsync(DeviceCommand command, CancellationToken cancellationToken)
|
||||
public Task SendAsync(DeviceCommand command, CancellationToken cancellationToken) =>
|
||||
SendIfAsync(command, null, cancellationToken);
|
||||
|
||||
public async Task<string?> SendIfAsync(DeviceCommand command,
|
||||
Func<IReadOnlyList<HomeAssistantState>, string?>? getSkipReason, CancellationToken cancellationToken)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
if (string.IsNullOrWhiteSpace(command.EntityId))
|
||||
@@ -43,9 +52,18 @@ public sealed class DeviceActionRunner
|
||||
using var bounded = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, timeout.Token);
|
||||
try
|
||||
{
|
||||
IReadOnlyList<HomeAssistantState>? states = null;
|
||||
if (getSkipReason is not null)
|
||||
{
|
||||
states = await _gateway.GetStatesAsync(bounded.Token);
|
||||
var reason = getSkipReason(states);
|
||||
if (reason is not null) return reason;
|
||||
}
|
||||
if (command.ValidateCurrentState is not null)
|
||||
command.ValidateCurrentState(await ReadAvailableStateAsync(command.EntityId, bounded.Token));
|
||||
command.ValidateCurrentState(states is null ? await ReadAvailableStateAsync(command.EntityId, bounded.Token)
|
||||
: RequireAvailableState(states, command.EntityId));
|
||||
foreach (var rule in _safety) await rule.ValidateAsync(command, bounded.Token);
|
||||
bounded.Token.ThrowIfCancellationRequested();
|
||||
await _gateway.CallServiceAsync(command.Domain, command.Service, command.ToServiceData(), bounded.Token);
|
||||
}
|
||||
catch (OperationCanceledException) when (!cancellationToken.IsCancellationRequested && timeout.IsCancellationRequested)
|
||||
@@ -53,6 +71,7 @@ public sealed class DeviceActionRunner
|
||||
throw new TimeoutException($"{command.Name}发送超时,未确认完成");
|
||||
}
|
||||
foreach (var rule in _safety) rule.Accepted(command, _time.GetUtcNow());
|
||||
return null;
|
||||
}
|
||||
finally { _commandGate.Release(); }
|
||||
}
|
||||
@@ -122,7 +141,8 @@ public sealed class DeviceActionRunner
|
||||
var state = states.FirstOrDefault(item => string.Equals(item.EntityId, command.EntityId, StringComparison.OrdinalIgnoreCase));
|
||||
var actual = state is null ? null : command.ExpectedAttribute is null
|
||||
? state.State : state.GetStringAttribute(command.ExpectedAttribute);
|
||||
if (state is not null && IsAvailable(state) && actual is not null && Matches(actual, command.ExpectedState!))
|
||||
if (state is not null && IsAvailable(state) && actual is not null && Matches(actual, command.ExpectedState!) &&
|
||||
(command.ExpectedEntityState is null || Matches(state.State, command.ExpectedEntityState)))
|
||||
{
|
||||
action.Status = "Succeeded"; action.Message = round == 0 ? "已回读确认目标状态" : "重试后已回读确认目标状态";
|
||||
pending.Remove(command); continue;
|
||||
@@ -130,6 +150,8 @@ public sealed class DeviceActionRunner
|
||||
if (round == attempts - 1)
|
||||
{
|
||||
action.Status = "Failed"; action.Message = $"未确认目标{(command.ExpectedAttribute is null ? "状态" : command.ExpectedAttribute)} {command.ExpectedState}(当前:{actual ?? "未读取到"})";
|
||||
if (command.ExpectedEntityState is not null)
|
||||
action.Message += $",同时要求状态 {command.ExpectedEntityState}(当前:{state?.State ?? "未读取到"})";
|
||||
pending.Remove(command); continue;
|
||||
}
|
||||
if (!command.RetryOnVerificationMismatch) continue;
|
||||
|
||||
Reference in New Issue
Block a user