CS_LEVEL_18_SOLUTION - OnlyCook/abitur-elite-code GitHub Wiki
public class Rover
{
private static int autowert = 0;
private int fahrzeugNr;
private string id;
public Rover(string id)
{
this.id = id;
this.fahrzeugNr = ++autowert;
}
public int GetFahrzeugNr()
{
return fahrzeugNr;
}
public void Unlock() { }
public void Lock() { }
}
public class Controller
{
private Rover rover;
private RFIDReader reader;
private Serial serial;
private FunkModul funk;
public Controller(string port, Rover r)
{
this.rover = r;
this.serial = new Serial(port, 9600, 8, 1, 0);
this.reader = new RFIDReader(serial);
this.funk = new FunkModul();
}
public void Run()
{
while (true)
{
if (reader.IsCardAvailable())
{
string id = reader.ReadCard();
if (id != "")
{
funk.Send($"UNLOCK {rover.GetFahrzeugNr()} {id}");
if (funk.Receive() == 0x06)
{
rover.Unlock();
}
}
}
}
}
}Das Neue an der Rover-Klasse ist der statische Zähler zur automatischen Vergabe der Fahrzeugnummer:
private static int autowert = 0;Ein static-Attribut gehört nicht zu einem einzelnen Objekt, sondern zur Klasse selbst. Alle Rover-Instanzen teilen sich denselben autowert. Jedes Mal, wenn ein neuer Rover erzeugt wird, wird der Zähler um 1 erhöht – und genau dieser erhöhte Wert wird als Fahrzeugnummer gespeichert:
this.fahrzeugNr = ++autowert;Das ++ vor der Variable ist entscheidend: Pre-Inkrement erhöht autowert zuerst und gibt dann den neuen Wert zurück. Der erste Rover bekommt also fahrzeugNr = 1, der zweite 2, und so weiter. Mit Post-Inkrement (autowert++) würde der erste Rover die 0 bekommen – falsch.
Im Abitur taucht dieses Muster regelmäßig auf. Sobald du static int autowert = 0 im Klassendiagramm siehst, ist ++autowert im Konstruktor die erwartete Lösung.
public Controller(string port, Rover r)
{
this.rover = r;
this.serial = new Serial(port, 9600, 8, 1, 0);
this.reader = new RFIDReader(serial);
this.funk = new FunkModul();
}Der Rover wird von außen übergeben, alle anderen Abhängigkeiten werden intern erstellt. Die Reihenfolge ist dabei wichtig: serial muss vor reader erstellt werden, weil RFIDReader das serial-Objekt im Konstruktor erwartet. Das serial-Objekt öffnet sich dann automatisch im RFIDReader-Konstruktor – genau so, wie wir es in Level 17 implementiert haben.
Die Parameter für Serial stehen im Material: 9600 Baud, 8 Datenbits, 1 Stoppbit, 0 für kein Paritätsbit.
while (true)
{
if (reader.IsCardAvailable())
{
string id = reader.ReadCard();
if (id != "")
{
funk.Send($"UNLOCK {rover.GetFahrzeugNr()} {id}");
if (funk.Receive() == 0x06)
{
rover.Unlock();
}
}
}
}while (true) ist die klassische Endlosschleife – sie läuft so lange, bis das Programm von außen beendet wird. Im Abitur steht das oft für den Dauerbetrieb eines eingebetteten Systems.
Der Ablauf folgt einer klaren Kette:
- Erst prüfen, ob überhaupt eine Karte da ist (
IsCardAvailable()). - Karte auslesen – gibt
ReadCard()einen Leerstring zurück, war das Paket ungültig, also nichts tun. - Ist die ID gültig, den Funk-Befehl senden:
"UNLOCK <FahrzeugNr> <CardID>"– String-Interpolation mit$wie bekannt. - Auf das ACK-Byte
0x06warten: Erst wenn das Funkmodul mit ACK antwortet, wirdrover.Unlock()aufgerufen. Das ist eine einfache Quittierung – der Rover wird nur freigegeben, wenn die Gegenstelle bestätigt hat.
Diese Struktur – prüfen, lesen, validieren, handeln – ist ein typisches Muster für Hardware-nahe Kommunikation im Abitur.