This commit is contained in:
fuenmao
2026-11-12 15:45:52 +08:00
parent 61e25175db
commit 718b138033
30 changed files with 1511 additions and 99 deletions
@@ -13,22 +13,30 @@ public sealed class IndoorEnvironmentReader
public IndoorEnvironmentReader(IOptions<HomeAssistantOptions> options, TimeProvider time)
=> (_entities, _time) = (options.Value.Entities, time);
public IndoorTemperatureSample Read(IReadOnlyDictionary<string, HomeAssistantState> states)
public IndoorTemperatureSample Read(IReadOnlyDictionary<string, HomeAssistantState> states) =>
ReadState(string.IsNullOrWhiteSpace(_entities.Temperature) ? null : states.GetValueOrDefault(_entities.Temperature));
public IndoorTemperatureSample Read(IReadOnlyList<HomeAssistantState> states) =>
ReadState(states.LastOrDefault(state =>
string.Equals(state.EntityId, _entities.Temperature, StringComparison.OrdinalIgnoreCase)));
private IndoorTemperatureSample ReadState(HomeAssistantState? state)
{
if (string.IsNullOrWhiteSpace(_entities.Temperature) ||
!states.TryGetValue(_entities.Temperature, out var state) || !DeviceActionRunner.IsAvailable(state))
return new(null, null, false, "室内温度实体未配置或不可用");
if (state is null || !DeviceActionRunner.IsAvailable(state))
return new(null, null, false, "室内温度实体未配置或不可用") { Issue = IndoorTemperatureIssue.Unavailable };
var observedAt = state.LastReported ?? state.LastUpdated;
if (observedAt is null || _time.GetUtcNow() - observedAt > TimeSpan.FromMinutes(30) ||
observedAt > _time.GetUtcNow().AddMinutes(1))
return new(null, observedAt, false, "室内温度数据缺少有效时间或已过期");
var now = _time.GetUtcNow();
if (observedAt is null || now - observedAt > TimeSpan.FromMinutes(30) || observedAt > now.AddMinutes(1))
return new(null, observedAt, false, "室内温度数据缺少有效时间或已过期") { Issue = IndoorTemperatureIssue.Stale };
if (!double.TryParse(state.State, NumberStyles.Float, CultureInfo.InvariantCulture, out var celsius) ||
!double.IsFinite(celsius)) return new(null, observedAt, false, "室内温度数据无效");
!double.IsFinite(celsius))
return new(null, observedAt, false, "室内温度数据无效") { Issue = IndoorTemperatureIssue.Invalid };
var unit = state.GetStringAttribute("unit_of_measurement");
if (unit is "°F" or "F") celsius = (celsius - 32) * 5 / 9;
else if (!string.IsNullOrWhiteSpace(unit) && unit is not ("°C" or "C" or "℃"))
return new(null, observedAt, false, "室内温度单位未识别");
if (celsius is < -20 or > 60) return new(null, observedAt, false, "室内温度超出有效范围");
return new(null, observedAt, false, "室内温度单位未识别") { Issue = IndoorTemperatureIssue.Invalid };
if (celsius is < -20 or > 60)
return new(null, observedAt, false, "室内温度超出有效范围") { Issue = IndoorTemperatureIssue.Invalid };
return new(celsius, observedAt, true, "室内温度数据有效");
}
}