11 KiB
adas-core.module.LightBeacons — Light Beacon Module
A functional module of the ADAS Core platform. Encapsulates all logic for managing, controlling, and monitoring light beacon devices deployed at Points of Care. This module operates as an independent satellite that the Host registers at startup, maintaining full separation from unrelated domain concerns.
Table of Contents
- Overview
- Responsibilities
- Project Structure
- Dependencies
- Device Abstraction
- Beacon Control Flow
- LightBeaconService Orchestration
- Design Rules
Overview
adas-core.module.LightBeacons is a modular satellite project that encapsulates every concern related to light beacon hardware within the ADAS Core ecosystem. It is responsible for discovering beacon configurations, translating clinical observation statuses into color commands, dispatching those commands to physical devices, and broadcasting state changes to connected subscribers.
Key characteristics:
- Modular Monolith Pattern — Operates as a self-contained module with its own device drivers, service logic, and repository interactions. No other module depends on it.
- Polymorphic Devices — Supports multiple beacon hardware models via an abstract
LightBeaconbase class. New models are added by inheriting from the base and registering the type string inLightBeaconService. - State Caching — Maintains an in-memory
ConcurrentDictionaryof current beacon colors per Point-of-Care to avoid redundant commands. - Subscriber Broadcasting — Pushes beacon color changes to WebSocket / SignalR subscribers via
IClientMessageService. - HTTP-Based Drivers — Current concrete implementation (
Turktbens2LightBeacon) communicates over HTTP, parses HTML status pages, and sends form-encoded commands.
Responsibilities
| Concern | What this project does |
|---|---|
| Device Abstraction | Defines LightBeacon and LightBeaconAbstract base classes that every beacon driver implements. |
| Hardware Control | Sends color commands (red, blue, yellow, off) to physical beacon devices over the network. |
| Status Retrieval | Reads the current color state from a beacon by scraping its web interface or calling its API. |
| Color Alert Generation | Translates PatientObservation status (Warning / Alert) into the configured beacon color. |
| Configuration CRUD | Manages beacon device configurations (name, URL, port, password, type) through ILightBeaconRepository. |
| Association Management | Links beacons to Points of Care via Configuration.BeaconIdList. |
| State Caching | Tracks per-PoC color in memory to suppress duplicate commands. |
| Subscriber Broadcast | Notifies all subscribers of a PoC when the beacon color changes via BeaconResponse. |
| Retry Logic | Implements exponential-backoff retry for transient network failures when sending commands. |
| Audit Logging | Emits audit events for beacon state changes and configuration mutations. |
Project Structure
adas-core.module.LightBeacons/
├── Devices/
│ ├── LightBeacon.cs # Abstract base class for all beacon drivers
│ ├── LightBeaconAbstract.cs # Legacy abstract base with static factory
│ └── Turktbens2LightBeacon.cs # Concrete HTTP-based driver for TURKTBENS2
│
└── Services/
└── LightBeaconService.cs # Orchestrates beacon control, caching, and broadcasting
| File | Role |
|---|---|
LightBeacon.cs |
Abstract base defining BlueCode(), RedCode(), YellowCode(), PowerOffLed(), GetBeaconColor(), and GenerateColorAlert(). |
LightBeaconAbstract.cs |
Older abstraction with Host/Password fields and reflection-based static factory GetBeaconDevice(). |
Turktbens2LightBeacon.cs |
HTTP driver: parses HTML status pages, sends form-encoded commands, retry with exponential backoff, emulation mode. |
LightBeaconService.cs |
Service implementing ILightBeaconService. Mediates between Application-layer commands and physical devices. |
Dependencies
Downstream References
| Project | Role |
|---|---|
adas-core.Application |
Consumes ILightBeaconRepository, IPointOfCareService, ISubscribersService, IClientMessageService, and ILightBeaconService interface. |
adas-core.Domain |
Uses LightBeaconColor, PatientObservation, StatusEnum, PointOfCare, BeaconResponse, OperationType, EquatableDictionary, and domain exceptions. |
Upstream References (projects that depend on this)
| Project | Reason |
|---|---|
adas-core (Host) |
Registers the module at startup. Host controllers invoke ILightBeaconService endpoints. |
adas-core.Infrastructure |
LightBeaconRepository (in Infrastructure) implements ILightBeaconRepository defined in Application. |
NuGet Packages
| Package | Version | Purpose |
|---|---|---|
HtmlAgilityPack |
1.12.4 | HTML DOM parsing for scraping beacon status pages. |
AuditLogs |
1.0.59 | Audit tagging on beacon state transitions and configuration changes. |
Device Abstraction
LightBeacon (Primary Async Abstraction)
The main device contract for all modern beacon drivers:
public abstract class LightBeacon(EquatableDictionary<string, object> options)
{
public abstract Task BlueCode();
public abstract Task RedCode();
public abstract Task YellowCode();
public abstract Task PowerOffLed();
public abstract Task GenerateColorAlert(PatientObservation obs);
public abstract Task<LightBeaconColor> GetBeaconColor();
}
Turktbens2LightBeacon (Concrete Driver)
- Communication — HTTP POST to the beacon's embedded web server.
- Status Reading — Scrapes
/IO01_03.htmland/IO12_03.html, parses checkbox states withHtmlAgilityPack. - Command Mapping — Converts
LightBeaconColorto a 3-bit binary code sent as form fields. - Retry Policy — Exponential backoff (500 ms -> 1 s -> 2 s) with max 3 retries on network failures.
- Emulation Mode — When
emulate: true, skips HTTP calls and returnsLightBeaconColor.Offfor reads. - Port Selection — Supports multi-port beacons (ports 1-4) via
_portMappings.
Beacon Control Flow
[PatientObservation Status Change] --> [LightBeaconService.GenerateColorAlert]
|
v
[Map StatusEnum -> LightBeaconColor]
[Warning -> WarnColor, Alert -> AlertColor]
|
v
[GetBeacon(beaconId)]
[Resolve device from config.Type]
|
v
[SendColor(poc, color)]
[Cache check: skip if unchanged]
|
v
[Dispatch to physical device]
[Turktbens2: HTTP POST with retry]
|
v
[Update in-memory cache]
[SendBeaconBroadcast -> subscribers]
|
v
[Return / Log]
LightBeaconService Orchestration
Color Dispatch
| Method | Behavior |
|---|---|
SendColor(pocId, color) |
Resolves PoC, retrieves associated beacons, dispatches color command, updates cache, broadcasts. |
PowerOffLed(pocId) |
Sets all associated beacons to LightBeaconColor.Off, updates cache. |
GetColor(pocId) |
Returns cached color or queries the physical beacon for current state. |
Alert Generation
GenerateColorAlert(PatientObservation) converts:
StatusEnum.Type.Warning->obs.WarnColor(e.g.,"Yellow","001")StatusEnum.Type.Alert->obs.AlertColor(e.g.,"Red","100")- Other ->
LightBeaconColor.Off
The method builds an HTTP form body and sends it via SendMessage.
Broadcasting
SendBeaconBroadcast(poc, color):
- Queries
ISubscribersService.GetSubscribers()filtered byLocationIds. - Builds a
BeaconResponse(color string, PoC ID, Unit ID). - Sends to each subscriber via
IClientMessageService.SendAsync(..., OperationType.Beacon, ...).
This drives real-time UI updates in client applications.
Configuration CRUD
| Method | Behavior |
|---|---|
InsertOne(beacon) |
Validates uniqueness by name, inserts via repository. |
UpdateOne(beacon) |
Updates record, returns refreshed entity. |
GetPaginatedBeacons(filter) |
Paginated list with InUse flag computed from PointOfCare associations. |
GetSearchByName(text) |
Partial-match search on beacon names. |
State Caching
_locationsWithColor is a ConcurrentDictionary<ObjectId, LightBeaconColor> keyed by PoC ID:
- Prevents redundant commands when the requested color matches the cached color.
- Updated under
lock()during writes to avoid race conditions. - Falls back to device query when the PoC is not in the cache.
Design Rules
- Module Independence — No project outside Infrastructure depends on this module. The Host registers it via assembly scan.
- Device Abstraction — All hardware-specific code is isolated in
Devices/.LightBeaconServiceonly sees theLightBeaconbase type. - No Blocking Calls — Modern drivers use async/await exclusively. Legacy
LightBeaconAbstractremains synchronous but is deprecated. - Cache Consistency — In-memory cache is always updated after a successful physical-device command, never before.
- Graceful Degradation — Network failures return
LightBeaconColor.Offrather than crashing the observation pipeline. - Retry Discipline — Exponential backoff capped at 3 attempts. Logs each retry attempt with
Warning, final failure withError. - Audit Emission — Every
InsertOne,UpdateOne,SendColor, andPowerOffLedemits an audit event. - Configuration-Driven — Beacon URL, port, password, timeout, and emulation flag all come from
LightBeacon.Options. No hardcoded device addresses. - Factory Extensibility — Adding a new beacon model requires only: (a) inherit
LightBeacon, (b) add acaseinLightBeaconService.GetBeacon, (c) register in DI. No other code changes. - Broadcast Decoupling —
IClientMessageServiceis an injected abstraction. Replacing SignalR with WebSockets or SSE requires no changes in this module.
Back to adas-core Root README