using Akka.Actor; using Akka.Hosting; using Microsoft.AspNetCore.SignalR; using Microsoft.Extensions.DependencyInjection; namespace ZB.MOM.WW.OtOpcUa.AdminUI.Hubs; public static class HubServiceCollectionExtensions { public const string FleetStatusSignalRBridgeName = "fleet-status-signalr-bridge"; public const string AlertSignalRBridgeName = "alert-signalr-bridge"; public const string ScriptLogSignalRBridgeName = "script-log-signalr-bridge"; public const string DriverStatusSignalRBridgeName = "driver-status-signalr-bridge"; /// /// Registers the in-process live-push services the AdminUI's Blazor Server panels read /// directly (instead of self-connecting a SignalR HubConnection, which fails behind a /// reverse proxy — see ): /// /// — last-value snapshot per driver. /// — append-stream fan-out (alarm /// transitions, script-log lines). Registered as an open generic so each closed type /// resolves to its own singleton shared by the bridge actor and the consuming component. /// /// /// The service collection. public static IServiceCollection AddOtOpcUaDriverStatusServices(this IServiceCollection services) { services.AddSingleton(); services.AddSingleton(typeof(IInProcessBroadcaster<>), typeof(InProcessBroadcaster<>)); return services; } /// /// Spawns the SignalR bridge actors that forward DPS messages to browser-facing SignalR /// hubs: fleet-status, alerts → /// , script-logs. /// /// Call inside the admin-role configurator on the shared : /// /// if (hasAdmin) /// { /// ab.WithOtOpcUaControlPlaneSingletons(); /// ab.WithOtOpcUaSignalRBridges(); /// } /// /// /// The Akka configuration builder. public static AkkaConfigurationBuilder WithOtOpcUaSignalRBridges(this AkkaConfigurationBuilder builder) { builder.WithActors((system, registry, resolver) => { var fleetHub = resolver.GetService>(); var fleetBridge = system.ActorOf(FleetStatusSignalRBridge.Props(fleetHub), FleetStatusSignalRBridgeName); registry.Register(fleetBridge); var alertHub = resolver.GetService>(); var alertBroadcaster = resolver.GetService>(); var alertBridge = system.ActorOf(AlertSignalRBridge.Props(alertHub, alertBroadcaster), AlertSignalRBridgeName); registry.Register(alertBridge); var scriptLogHub = resolver.GetService>(); var scriptLogBroadcaster = resolver.GetService>(); var scriptLogBridge = system.ActorOf(ScriptLogSignalRBridge.Props(scriptLogHub, scriptLogBroadcaster), ScriptLogSignalRBridgeName); registry.Register(scriptLogBridge); var driverStatusHub = resolver.GetService>(); var driverStatusStore = resolver.GetService(); var driverStatusBridge = system.ActorOf(DriverStatusSignalRBridge.Props(driverStatusHub, driverStatusStore), DriverStatusSignalRBridgeName); registry.Register(driverStatusBridge); }); return builder; } } /// Marker keys for lookup of the SignalR bridge actors. public sealed class FleetStatusSignalRBridgeKey { } public sealed class AlertSignalRBridgeKey { } public sealed class ScriptLogSignalRBridgeKey { } public sealed class DriverStatusSignalRBridgeKey { }