ASTVariable(Of T) -- Generische Variable mit automatischer Aenderungserkennung
Uebersicht
ASTVariable(Of T) ist eine generische Wrapper-Klasse aus der ASTLibrary, die eine
beliebige Variable kapselt und bei Wertaenderungen automatisch reagiert. Die Klasse loest
drei moegliche Aktionen aus, wenn sich der Wert aendert:
- Automatisches Senden ueber
INetClient.DataTXan den ASTServer - Callback-Aufruf einer benutzerdefinierten
Action(Of T) - Event
ValueChangedfuer beliebige Subscriber
Diese drei Mechanismen koennen einzeln oder kombiniert genutzt werden. Dadurch entfaellt
die manuelle Pruefung auf Wertaenderungen -- der Code schreibt einfach .Value = neuerWert
und die Klasse uebernimmt den Rest.
Quelldatei: ASTLibrary/ASTLibrary/ASTVariable.vb
Klassendiagramm
classDiagram
class ASTVariable~T~ {
-T _value
-INetClient _inetClient
-Integer _cmd
-Action~T~ _onChange
+T Value
+Event ValueChanged(sender, newValue)
+New(initialValue : T)
+New(initialValue : T, inetClient : INetClient, cmd : Integer)
+New(initialValue : T, onChange : Action~T~)
+New(initialValue : T, inetClient : INetClient, cmd : Integer, onChange : Action~T~)
}
class INetClient {
+DataTX(CMD : Integer, ToModule : Byte, data : String)
+DataTXBit(CMD : Integer, ToModule : Byte, BitID : Byte, value : Byte)
}
ASTVariable~T~ --> INetClient : sendet via DataTX
Konstruktoren
Die Klasse bietet vier Konstruktoren fuer unterschiedliche Einsatzszenarien:
| Konstruktor | Beschreibung |
|---|---|
New(initialValue) |
Nur Anfangswert, ohne Auto-Senden oder Callback. Nuetzlich wenn nur das ValueChanged-Event verwendet wird. |
New(initialValue, inetClient, cmd) |
Automatisches Senden ueber INetClient.DataTX bei jeder Wertaenderung. Der cmd-Parameter ist die INET-Register-Nummer. |
New(initialValue, onChange) |
Ruft bei Wertaenderung die uebergebene Action(Of T) Callback-Methode auf. |
New(initialValue, inetClient, cmd, onChange) |
Kombiniert automatisches Senden und Callback. |
Aenderungserkennung (HasChanged-Mechanismus)
Die zentrale Logik liegt im Setter der Value-Property. Bei jeder Zuweisung wird
geprueft, ob sich der Wert tatsaechlich geaendert hat:
Public Property Value As T
Get
Return _value
End Get
Set(value As T)
' Pruefung ob sich der Wert tatsaechlich geaendert hat
If Not EqualityComparer(Of T).Default.Equals(_value, value) Then
_value = value
' 1. ValueChanged Event ausloesen
RaiseEvent ValueChanged(Me, value)
' 2. Falls InetClient definiert: DataTX aufrufen
If _inetClient IsNot Nothing Then
_inetClient.DataTX(_cmd, 0, value.ToString())
End If
' 3. Falls Callback definiert: Callback aufrufen
If _onChange IsNot Nothing Then
_onChange.Invoke(value)
End If
End If
End Set
End Property
Ablauf bei Wertzuweisung
flowchart TD
A["variable.Value = neuerWert"] --> B{"Wert geaendert?<br/>EqualityComparer(Of T).Default.Equals"}
B -- Nein --> Z["Nichts tun"]
B -- Ja --> C["_value = neuerWert"]
C --> D["RaiseEvent ValueChanged"]
D --> E{"INetClient<br/>vorhanden?"}
E -- Ja --> F["inetClient.DataTX(cmd, 0, wert)"]
E -- Nein --> G{"Callback<br/>vorhanden?"}
F --> G
G -- Ja --> H["onChange.Invoke(wert)"]
G -- Nein --> Z2["Fertig"]
H --> Z2
Wichtig: Wenn der zugewiesene Wert identisch mit dem aktuellen Wert ist, passiert gar nichts -- kein Event, kein Senden, kein Callback. Das verhindert unnoetige Netzwerk-Pakete und redundante Verarbeitung.
Kommunikation mit dem ASTServer
Wenn eine ASTVariable mit einem INetClient und einer CMD-Nummer konfiguriert ist,
wird bei jeder Wertaenderung DataTX aufgerufen:
Die DataTX-Methode des INetClient unterscheidet dabei zwei Faelle:
- CMD >= 2000: Sendet einen Frame mit der CMD-Nummer direkt als Frame-Typ
- CMD < 2000: Verpackt die CMD-Nummer fuenfstellig als Praefix in einen Frame vom Typ 5340
In beiden Faellen wird der Wert als String uebertragen. Der ToModule-Parameter wird
von ASTVariable immer als 0 (Broadcast an alle Module) uebergeben.
Verwendung im Code
Praxisbeispiel: FMA-Array im FCU-Modul
Das A320 FCU-Modul nutzt ASTVariable fuer die 15 Flight Mode Annunciator (FMA) Werte.
Jeder FMA-Slot ist an ein eigenes INET-Register (CMD 2263-2277) gebunden:
' Aus A320_FCU/Module/FCULogic/modVariablesFCULogic.vb
Public FMA As ASTLibrary.ASTVariable(Of Integer)() = {
New ASTLibrary.ASTVariable(Of Integer)(0, MainFormInstance.INetClient1, 2263),
New ASTLibrary.ASTVariable(Of Integer)(0, MainFormInstance.INetClient1, 2264),
New ASTLibrary.ASTVariable(Of Integer)(0, MainFormInstance.INetClient1, 2265),
New ASTLibrary.ASTVariable(Of Integer)(0, MainFormInstance.INetClient1, 2266),
New ASTLibrary.ASTVariable(Of Integer)(0, MainFormInstance.INetClient1, 2267),
New ASTLibrary.ASTVariable(Of Integer)(0, MainFormInstance.INetClient1, 2268),
New ASTLibrary.ASTVariable(Of Integer)(0, MainFormInstance.INetClient1, 2269),
New ASTLibrary.ASTVariable(Of Integer)(0, MainFormInstance.INetClient1, 2270),
New ASTLibrary.ASTVariable(Of Integer)(0, MainFormInstance.INetClient1, 2271),
New ASTLibrary.ASTVariable(Of Integer)(0, MainFormInstance.INetClient1, 2272),
New ASTLibrary.ASTVariable(Of Integer)(0, MainFormInstance.INetClient1, 2273),
New ASTLibrary.ASTVariable(Of Integer)(0, MainFormInstance.INetClient1, 2274),
New ASTLibrary.ASTVariable(Of Integer)(0, MainFormInstance.INetClient1, 2275),
New ASTLibrary.ASTVariable(Of Integer)(0, MainFormInstance.INetClient1, 2276),
New ASTLibrary.ASTVariable(Of Integer)(0, MainFormInstance.INetClient1, 2277)
}
Wenn die FCU-Logik einen FMA-Modus aendert, reicht eine einfache Zuweisung:
' Aus A320_FCU/modFCULogic.vb -- Autopilot-Modus setzen
FMA(AP_ROW1).Value = FMA_AP1_ ' Sendet automatisch via CMD 2263 + Offset
FMA(SPD_ROW1).Value = NONE_ ' Sendet nur wenn Wert sich aendert
FMA(AP_ROW3).Value = FMA_ATHR_STBY_ ' Kein manueller DataTX-Aufruf noetig
Der Vorteil: Der TEMP_FMA-Vergleich (der alte VB6-Ansatz mit manueller Pruefung)
wird durch die eingebaute Aenderungserkennung der ASTVariable ersetzt.
Weitere Konstruktor-Varianten (aus der XML-Dokumentation)
' Automatisches Senden ueber InetClient an ASTServer:
Public Altitude As New ASTVariable(Of Integer)(0, myInetClient, 100)
' Mit Callback-Sub:
Public Heading As New ASTVariable(Of Integer)(0, AddressOf OnHeadingChanged)
' Beides kombiniert:
Public VertSpeed As New ASTVariable(Of Integer)(0, myInetClient, 102, AddressOf OnVSChanged)
' Verwendung:
Altitude.Value = 10000 ' Sendet automatisch via myInetClient.DataTX(100, 0, "10000")
Typparameter
Da ASTVariable(Of T) generisch ist, kann jeder Datentyp verwendet werden. Die
Aenderungserkennung nutzt EqualityComparer(Of T).Default, was fuer alle
Standard-.NET-Typen korrekt funktioniert:
| Typ | Typischer Einsatz |
|---|---|
Integer |
FMA-Modi, Geschwindigkeiten, Hoehen, Heading |
Double |
Praezise Werte (EPR, Koordinaten, Winkel) |
String |
Textuelle Daten (Wegpunkt-Namen, Meldungen) |
Boolean |
Flags und Schalter |
Designentscheidungen
- Keine Synchronisation: Die Klasse ist nicht thread-safe. In der Akka.NET-Architektur des FMGC ist das korrekt, da jeder Actor seine eigenen Variablen in seinem eigenen Thread verarbeitet.
- ToString()-Serialisierung: Der Wert wird immer via
value.ToString()als String gesendet. Das entspricht dem VB6 INET-Protokoll, das ausschliesslich String-basiert ist. - Broadcast (ToModule = 0):
ASTVariablesendet immer an alle Module (ToModule = 0). Fuer gerichtetes Senden an ein bestimmtes Modul mussDataTXdirekt aufgerufen werden.