1
This commit is contained in:
@@ -0,0 +1,23 @@
|
||||
using Evergreen.Health.Application.Health.Devices.Contracts;
|
||||
using Evergreen.Health.Application.Health.Integrations.HomeAssistant;
|
||||
using Evergreen.Health.Application.Health.Models;
|
||||
using Evergreen.Health.Application.Health.Scenes;
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
namespace Evergreen.Health.Application.Health.Devices.Environment;
|
||||
|
||||
public sealed class EnvironmentModule : HealthDeviceModule
|
||||
{
|
||||
private readonly HomeAssistantEntityOptions _entities;
|
||||
public EnvironmentModule(DeviceActionRunner runner, IOptions<HomeAssistantOptions> options) : base(runner)
|
||||
=> _entities = options.Value.Entities;
|
||||
public override string Key => "environment";
|
||||
public override string Category => nameof(HealthDeviceCategory.EnvironmentSensor);
|
||||
public override string DisplayName => "室内环境检测仪";
|
||||
public override string PrimaryEntityId => "";
|
||||
public override IReadOnlyList<DeviceParameterDefinition> Parameters => [];
|
||||
public override IEnumerable<string> EntityIds => new[]
|
||||
{
|
||||
_entities.Temperature, _entities.Humidity, _entities.Pm25, _entities.Co2, _entities.Formaldehyde, _entities.Tvoc
|
||||
}.Where(id => !string.IsNullOrWhiteSpace(id)).Distinct(StringComparer.OrdinalIgnoreCase);
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
using Evergreen.Health.Application.Health.Integrations.HomeAssistant;
|
||||
using Evergreen.Health.Application.Health.Policies;
|
||||
using Evergreen.Health.Application.Health.Scenes;
|
||||
using Microsoft.Extensions.Options;
|
||||
using System.Globalization;
|
||||
|
||||
namespace Evergreen.Health.Application.Health.Devices.Environment;
|
||||
|
||||
public sealed class IndoorEnvironmentReader
|
||||
{
|
||||
private readonly HomeAssistantEntityOptions _entities;
|
||||
private readonly TimeProvider _time;
|
||||
public IndoorEnvironmentReader(IOptions<HomeAssistantOptions> options, TimeProvider time)
|
||||
=> (_entities, _time) = (options.Value.Entities, time);
|
||||
|
||||
public IndoorTemperatureSample Read(IReadOnlyDictionary<string, HomeAssistantState> states)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(_entities.Temperature) ||
|
||||
!states.TryGetValue(_entities.Temperature, out var state) || !DeviceActionRunner.IsAvailable(state))
|
||||
return new(null, null, false, "室内温度实体未配置或不可用");
|
||||
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, "室内温度数据缺少有效时间或已过期");
|
||||
if (!double.TryParse(state.State, NumberStyles.Float, CultureInfo.InvariantCulture, out var celsius) ||
|
||||
!double.IsFinite(celsius)) return new(null, observedAt, false, "室内温度数据无效");
|
||||
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(celsius, observedAt, true, "室内温度数据有效");
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user