4b0cad67df
- PayloadExtractor: dot-path value/time extraction (Tasmota ENERGY.Total, bare scalars). - MqttTopicMatcher: standard +/# wildcard matching. - IngestionService: scale/offset, idempotent upsert on (meter_id, time), and a spurious- decrease guard for monotonic registers (allowed only with a reset/swap event) + source last-seen status. - MqttMessageRouter + MqttIngestionWorker (MQTTnet 5): per-endpoint persistent connections, topic subscription, graceful degradation; secrets resolved by env-var reference. - Home Assistant: HaStateClient (REST /api/states parse) + HomeAssistantWorker polling on each source's interval. HA-via-MQTT also works through the MQTT path. - Ingestion workers gated by MeterVault:EnableLiveIngestion (off in tests). 85 tests green (53 Core + 32 integration): Tasmota payload → reading verified end to end. Follow-up (polish): HA WebSocket push (state_changed) as an alternative to REST poll; source-topic index caching in the router. Claude-Session: https://claude.ai/code/session_01WujdMtMJPbxDpDnMeK22rr
20 lines
780 B
C#
20 lines
780 B
C#
using Microsoft.AspNetCore.Hosting;
|
|
using Microsoft.AspNetCore.Mvc.Testing;
|
|
|
|
namespace MeterVault.Integration.Tests;
|
|
|
|
/// <summary>
|
|
/// Boots the real ASP.NET Core app in-memory against the shared Timescale container.
|
|
/// Migrations are already applied by <see cref="TimescaleFixture"/>, so startup migration is off.
|
|
/// </summary>
|
|
public sealed class MeterVaultAppFactory(string connectionString) : WebApplicationFactory<Program>
|
|
{
|
|
protected override void ConfigureWebHost(IWebHostBuilder builder)
|
|
{
|
|
builder.UseEnvironment("Testing");
|
|
builder.UseSetting("ConnectionStrings:Default", connectionString);
|
|
builder.UseSetting("MeterVault:RunMigrationsAtStartup", "false");
|
|
builder.UseSetting("MeterVault:EnableLiveIngestion", "false");
|
|
}
|
|
}
|