Alapfogalmak

A Komod felépítése

Egy Komod egy .NET osztály, amely a KomodBase<TSettings>-ből származik, és a [Komod] attribútummal van megjelölve. A KOFA a betöltéskor reflexióval olvassa ki belőle a portokat és a beállításokat, tehát semmit nem kell regisztrálnod.

[Komod("acme.demo.thermostat",
    DisplayName = "Termosztát",
    Description = "Hiszterézises termosztát: a hőmérséklet alapján kapcsolja a fűtést.",
    Category = KomodCategory.Controller)]
public sealed class ThermostatKomod : KomodBase<ThermostatSettings>
{
    // The input must be linked in the graph. If no message arrives for 5 seconds, OnInputTimeout runs (failsafe).
    [Input("temperature", DisplayName = "Hőmérséklet", Deadline = "00:00:05")]
    public required IInput<Scalar> Temperature { get; init; }

    [Output("heater", DisplayName = "Fűtés")]
    public required IOutput<BoolValue> Heater { get; init; }

    private bool _heating;

    protected override async Task ExecuteAsync(CancellationToken cancellationToken)
    {
        Context.ReportStatus(KomodHealth.Warning, "Nincs adat");
        SetHeater(false);

        await foreach (var message in Temperature.ReadAllAsync(cancellationToken))
        {
            var settings = Settings;
            var celsius = message.Value.Value;

            if (celsius < settings.TargetCelsius - settings.HysteresisCelsius)
                SetHeater(true);
            else if (celsius > settings.TargetCelsius + settings.HysteresisCelsius)
                SetHeater(false);

            Context.ReportStatus(KomodHealth.Ok, $"{celsius:0.0} °C → cél {settings.TargetCelsius:0.#} °C, fűtés {(_heating ? "BE" : "KI")}");
        }
    }

    // The deadline elapsed: with no measurement the safe state is "off".
    protected override void OnInputTimeout(IInputPort port)
    {
        SetHeater(false);
        Context.ReportStatus(KomodHealth.Warning, "Nincs hőmérséklet adat, a fűtés kikapcsolt");
    }

    protected override Task<bool> OnSettingsChangedAsync(ThermostatSettings oldSettings, ThermostatSettings newSettings) =>
        Task.FromResult(true);

    private void SetHeater(bool on)
    {
        _heating = on;
        Heater.Publish(new BoolValue(on));
    }
}

Az építőelemek

Elem Mire való
[Komod("id", …)] Azonosító (kisbetűs, stabil), megjelenített név, leírás, kategória, járműtípus. A Komod attribútum minden tulajdonsága ott olvasható.
KomodBase<TSettings> Az ős. A TSettings egy rekord (alapértékekkel, new()-val példányosítható). Beállítás nélküli Komodhoz: KomodBase.
[Input] / [Output] Típusos portok, IInput<T> / IOutput<T> property-ként. Portok.
Context A példány szolgáltatásai: azonosító, naplózás, óra, tároló mappa, hardver, állapotjelzés. Lásd API referencia.
[KomodCommand] A böngészőből hívható metódus. Parancsok.

Példányok

Egy Komod típus; a gráfban annak példányai futnak, mindegyik a saját beállításaival és állapotával. Ugyanabból a Komodból több példány is lehet (két hőmérő), kivéve ha a MaxInstances korlátozza. A példány azonosítóját a Context.InstanceId adja, a gráfbeli nevét az InstanceLabel.

Kategóriák és járműtípusok

A Category (Source, Sensor, Controller, Actuator, Vision, Ai, Visualization, Converter, Service, System, Connectivity, Other) szerint csoportosít a gráf palettája és a Komod tár. A VehicleTypes (Car, Sailboat, Any) azt jelzi, melyik járműhöz való.

Több Komod egy csomagban

Egy csomag több Komod osztályt is tartalmazhat (például egy szenzor és a hozzá tartozó átalakító). A csomag azonosítója és verziója közös; a Komodok azonosítói külön vannak.

Mit tegyél, és mit ne

  • A ExecuteAsync-ben ne blokkolj (Thread.Sleep, .Result): aszinkron várj, és figyeld a CancellationToken-t.
  • Ne tárolj állapotot statikus mezőben: a csomag újratölthető (hot reload), és egy típusból több példány is futhat.
  • A saját adattípusaid a Komod csomagodba kerüljenek, lásd Saját típusok.