feat(mqtt): factory + DriverTypeNames.Mqtt + host factory/probe registration
Task 9. Adds MqttDriverFactoryExtensions (DriverTypeName = DriverTypeNames.Mqtt, direct deserialization of MqttDriverOptions — no intermediate DTO, mirroring OpcUaClientDriverFactoryExtensions), the DriverTypeNames.Mqtt constant, and both host wiring sites: the factory in DriverFactoryBootstrap.Register and the probe in AddOtOpcUaDriverProbes (the admin-node path Program.cs calls in its hasAdmin block — a probe wired only on driver nodes makes Test-connect silently dead). Carried-forward items: - Converges every MQTT config-parsing seam onto ONE JsonSerializerOptions — MqttJson.Options, in .Contracts alongside MqttDriverOptions. It replaces the probe's internal JsonOpts and the browser's separate private copy; the factory, the probe, MqttDriver.ParseOptions and MqttDriverBrowser now all parse through it. .Contracts is the only assembly all four consumers reference, and the browser's reference to the runtime .Driver project is a documented layering exception scheduled for removal — anchoring the options there would resurrect the duplicate the day it goes away. - Replaces the "Mqtt" literals in MqttDriverProbe, MqttDriverBrowser and MqttDriver with the constant (string value unchanged). - Tightens MqttDriverProbeTests.ProbeAsync_EnumAsName: it asserted only Ok == false + non-empty message, which is also exactly what a JSON-parse failure produces — so it stayed green under the very regression it names. It now asserts the probe got past the parse and reached the network. Falsifiability: deleting JsonStringEnumConverter from MqttJson.Options reddens 9 tests across 4 suites, including the tightened probe test (message becomes "Config JSON is invalid: The JSON value could not be converted to MqttProtocolVersion") — which the pre-fix assertions would have passed. Also references the MQTT driver from Core.Abstractions.Tests so DriverTypeNamesGuardTests' reflective bin scan discovers the new factory and the constant/factory parity check stays honest. Claude-Session: https://claude.ai/code/session_01GASWkNEi68FSCtvr6rLoEW
This commit is contained in:
@@ -2,7 +2,6 @@ using System.Diagnostics;
|
||||
using System.Net.Sockets;
|
||||
using System.Security.Authentication;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
using Microsoft.Extensions.Logging.Abstractions;
|
||||
using MQTTnet;
|
||||
using ZB.MOM.WW.OtOpcUa.Core.Abstractions;
|
||||
@@ -55,26 +54,8 @@ public sealed class MqttDriverProbe : IDriverProbe
|
||||
/// </summary>
|
||||
internal const string ProbeClientIdPrefix = "-probe-";
|
||||
|
||||
/// <summary>
|
||||
/// Shared JSON options for every MQTT config-parsing seam in this driver: enums
|
||||
/// (<see cref="MqttMode"/>, <see cref="MqttPayloadFormat"/>, <c>protocolVersion</c>)
|
||||
/// round-trip by <b>name</b>, never ordinal — the repo's documented enum-serialization
|
||||
/// trap (AdminUI-authored configs with numeric enum fields fault the driver). Task 9's
|
||||
/// <c>MqttDriverFactoryExtensions</c> is expected to converge on this same instance
|
||||
/// rather than defining its own.
|
||||
/// </summary>
|
||||
internal static readonly JsonSerializerOptions JsonOpts = new()
|
||||
{
|
||||
PropertyNameCaseInsensitive = true,
|
||||
UnmappedMemberHandling = JsonUnmappedMemberHandling.Skip,
|
||||
Converters = { new JsonStringEnumConverter() },
|
||||
};
|
||||
|
||||
/// <inheritdoc />
|
||||
// Literal rather than a constant: DriverTypeNames.Mqtt does not exist yet — Task 9 adds it, and
|
||||
// owns that file. The string must stay EXACTLY "Mqtt": a DriverType string that drifts from the
|
||||
// persisted one silently breaks driver dispatch (the repo's ModbusTcp/Modbus incident).
|
||||
public string DriverType => "Mqtt";
|
||||
public string DriverType => DriverTypeNames.Mqtt;
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<DriverProbeResult> ProbeAsync(string configJson, TimeSpan timeout, CancellationToken ct)
|
||||
@@ -82,7 +63,10 @@ public sealed class MqttDriverProbe : IDriverProbe
|
||||
MqttDriverOptions? options;
|
||||
try
|
||||
{
|
||||
options = JsonSerializer.Deserialize<MqttDriverOptions>(configJson, JsonOpts);
|
||||
// MqttJson.Options — the one shared instance across factory / probe / driver / browser
|
||||
// (see its remarks): enums must round-trip by NAME or an AdminUI-authored config that
|
||||
// Test-connect accepts would fault the deployed driver.
|
||||
options = JsonSerializer.Deserialize<MqttDriverOptions>(configJson, MqttJson.Options);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user