En C#-klasse til kommunikation med z21, z21Start, Z21 og Z21 XL centralstationerne til modeltogsbaner fra Roco/Fleischmann.
Z21Client-klassen understøtter følgende funktioner:
- Sprogversionering, dansk/tysk når sprog i Windows er sat til dansk/tysk. For alle andre sprog vises tekster på engelsk
- Forbindelse til Z21 via UDP
- Modtage information om lokomotiver (hastighed, retning, funktioner, protokol), når andre styreenheder bruges
- Modtage information om sporskifter/points (position, protokol), når andre styreenheder bruges
- Sende kommandoer til styring af lokomotiver (hastighed, retning, funktioner, protokol)
- Sende kommandoer til styring af sporskifter/points (position, protokol)
- Læse feedback fra Z21 (f.eks. lokomotivstatus)
- Understøttelse af flere lokomotiver
- Event-drevet arkitektur til håndtering af svar og opdateringer
- Asynkrone operationer for ikke-blokerende kommunikation
- Fejlhåndtering og genforbindelseslogik
- Understøttelse af protokoller brugt af z21/Z21 (DCC, Märklin Motorola)
- Logging-muligheder til fejlfinding og overvågning
- Z21Client er udviklet efter “AI Pair Programming” metoden
Du kan se og hente kildekoden til Z21Client i mit Github repo her:
https://github.com/J-Wachs/Z21Client
Nyheder i version af 3. august 2026
- Tilføjet meddelelser på tysk. Bemærk venligst, at de tyske meddelelser er oversat af en AI, og derfor kan være mindre korrekte end de danske og engelske meddelelser.
- Tilføjet mange nye tests til testprojektet
z21 og z21Start låseinformation
Hvis din z21 eller z21Start er låst, kan du stadig sende kommandoer til den med denne klasse. Dog vil kommandoerne blive ignoreret af z21/z21Start.
Hvis z21/z21Start er låst, kan du stadig bruge Z21Client-klassen til at skrive et overvågningsprogram, der læser status for lokomotiver og sporskifter/points. Du kan også kalde metoder i Z21Client til at skifte protokol på lokomotiver og sporskifter/sporskiftedekodere. Du kan læse mere om hvilke metoder (der pakker z21 kommandoer ind) der kan kaldes når z21/z21Start er låst, i den officielle Z21 LAN Protcol dokomentation, på Z21s hjemmeside.
Bemærk, at da z21 (i hvidt kabinet) oprindeligt blev lanceret, var nogle låste og andre ulåste. For at låse din z21 eller z21Start op, kan du købe en oplåsningskode:
- Roco varenummer 10814. Indeholder et trådløst access-point samt oplåsningskode til z21Start og z21 (hvidt kabinet)
- Roco varenummer 10818. Indeholder oplåsningskode til z21Start og z21 (hvidt kabinet)
Fra nu af vil betegnelsen Z21 blive brugt om alle fire versioner af Z21-familien af centralstationer. Hvis noget kun gælder én af versionerne, vil det blive angivet.
Z21Client blev udviklet og testet ved brug af to z21Start centralstationer: én låst og én ulåst. Dette er grunden til, at hverken LocoNet- eller CAN-bus-funktionalitet er implementeret i Z21Client-klassen.
Implementeringen er baseret på Roco-dokumentet “Z21 LAN Protocol Specification”, version 1.13 EN, dateret 6. november 2023. Dokumentet kan downloades fra Z21-websitet.
Fuldt funktionelt eksempelprojekt
For at se et eksempel på brugen af Z21Client, besøg venligst mit projekt Z21Dashboard på Github:
https://github.com/J-Wachs/Z21Dashboard
Hvordan virker det?
Z21Client-klassen bruger UDP til at kommunikere med Z21-centralen. I din applikation skal du først oprette forbindelse til Z21.
Da arkitekturen i Z21Client-klassen er event-drevet, skal du abonnere på de events, du ønsker at håndtere i din applikation. For eksempel skal du abonnere på eventet LocoStatusReceived for at håndtere opdateringer af lokomotivstatus.
De nødvendige ændringer af broadcast-flagene på Z21 bliver automatisk håndteret af Z21Client-klassen, når du tilføjer din metode til Z21Client-eventet.
Eksempel på abonnement på LocoStatusReceived-eventet:
...
@using IZ21Client Z21Client
...
...
Z21Client.LocoInfoReceived += OnLocoInfoReceived;
...
private async void OnLocoInfoReceived(object? sender, LocoInfo e)
{
// Håndter modtaget lokomotivinfo
Console.WriteLine($"Loco Info Received: Address={e.Address}, Speed={e.CurrentSpeed}, Direction={e.Direction}");
}
Implementering af Märklin Motorola-protokol i Z21Client vs i Z21
Z21 understøtter både DCC og Märklin Motorola protokoller til styring af lokomotiver. Følgende versioner af protokollerne er implementeret som følger:
- DCC, 14 trin: Protokol = DCC, hastighedstrin = 14
- DCC, 28 trin: Protokol = DCC, hastighedstrin = 28
- DCC, 128 trin: Protokol = DCC, hastighedstrin = 128
- Märklin Motorola 1, 14 trin: Protokol = Märklin Motorola, hastighedstrin = 14
- Märklin Motorola 2, 14 trin: Protokol = Märklin Motorola, hastighedstrin = 28
- Märklin Motorola 2, 28 trin: Protokol = Märklin Motorola, hastighedstrin = 128
På grund af dette rapporterer Z21 hastighedstrinene som 14, 28 eller 128, også når Märklin Motorola benyttes. Z21Client er udviklet til at afspejle protokollen og hastighedstrinene, som man normalt ville forvente. Derfor vil hastighedstrinene ved Märklin Motorola være hhv. 14, 14 eller 28.
Klassen LocoInfo, som bruges i Z21Client, afspejler denne implementering og indeholder to hastigheds-egenskaber:
- SpeedSteps: Hastighedstrin som implementeret i Z21Client (DCC: 14, 28, 128; MM: 14, 14, 28)
- NativeSpeedSteps: Hastighedstrin som implementeret i Z21. Altid 14, 28 eller 128 – også for MM-protokollen.
Ansvarsfraskrivelse: Implementering af ikke-dokumenteret ‘Locomotive Slot Information’
Roco har i deres værktøj Maintenance Tool en mulighed for at se de 120 lokomotiv-slots, der findes i Z21. Men den officielle “Z21 LAN Protocol Specification” dokumentation nævner ikke kommandoen og svaret til at læse disse slots. Ved at overvåge dataudvekslingen mellem mine Z21 (to z21Start, én låst, én ulåst) kunne jeg se kommandoerne. På grund af dette har jeg implementeret udokumenteret funktionalitet. Den virker i firmware 1.43 (en del af Maintenance Tool V1.18.3). Der gives ingen garanti for, at den vil virke i fremtidige firmwareudgaver.
Workaround for Z21 firmware-fejl
I den seneste firmwareversion (1.43) for Z21-familien er der efter min vurdering en fejl. Når man eksplicit forespørger lokomotivinformation (dvs. kalder Z21-kommandoen LAN_X_GET_LOCO_INFO, indkapslet i Z21Client.GetLocoInfoAsync()), vil protokol-bitten i byte DB2 i svaret ikke blive sat for lokomotiver, der er konfigureret til Märklin Motorola. Dog er protokol-bitten korrekt sat i events, der skyldes ændringer af lokomotivet (f.eks. hastighed, retning, funktionstaster).
For at omgå denne fejl forespørger Z21Client protokollen for lokomotivet separat og leverer derefter korrekt protokol i LocoInfoReceived-eventet.
Installationsvejledning
Hentning og afprøvning af Z21Client-klassen
Download repoet og opret et projekt, hvor du vil bruge Z21Client. Hvis du mangler inspiration, kan du se mit projekt Z21Dashboard på Github:
https://github.com/J-Wachs/Z21Dashboard
Opsætning af dit eget projekt til at bruge Z21Client-klassen
For at bruge Z21Client-klassen i dine egne projekter skal du tilføje komponentprojektet til din løsning. Derefter skal du tilføje Z21Client til Program.cs eller MauiProgram.cs i dit projekt:
... // Tilføjet for Z21Client builder.Services.AddSingleton<IZ21UdpClient, Z21UdpClient>(); builder.Services.AddSingleton<IZ21Client, Z21Client>(); // Slut ...
Tilpasning af Z21Client til eget brug
Måske har du brug for flere oplysninger. Måske skal du bruge en konfigurationsværdi til nogle af de data, der returneres. Måske har du brug for én af LocoNet- eller CAN-bus-kommandoerne/events.
Du er meget velkommen til at tilpasse en lokal version til dine behov.
Fundet en fejl?
Opret venligst et issue i repoet.
Kendte problemer (pågør)
Ingen på nuværende tidspunkt.
FAQ
Når jeg kalder metoden QueryForZ21s vises min Z21 ikke
Listen som metoden returnerer er tom, og du får ingen fejl. Du kan forbinde med Z21Client til din Z21 centralstation (alle modeller), og sende kommandoer og modtage data. At metoden returnerer en tom liste, sker typisk når pc’en er koblet på netværket trådløst.
For at finde Z21’ere på netværket udsender QueryForZ21s en UDP-broadcast som Z21 centralstationerne skal svare på. Mange access points og routere blokerer for UDP-broadcasts, og det er derfor muligt, at din Z21 ikke modtager broadcastet og derfor ikke svarer på det. Det er også muligt, at din pc ikke modtager svaret fra Z21.
Kik i opsætningen af dit access point eller router og se, om der er en indstilling for at blokere for UDP-broadcasts. Hvis det er tilfældet, skal du slå denne indstilling fra. Visse routere og access points har også en indstilling for at blokere for UDP-broadcasts på det trådløse net alene. Andre access points og routere har ikke en indstilling, men blokerer for UDP-broadcasts på det trådløse net som standard. I dette tilfælde kan du prøve at forbinde din pc til netværket med kabel for at se, om det løser problemet. Hvis det gør det, er det sandsynligt, at dit access point eller router blokerer for UDP-broadcasts på det trådløse net.
Vil du implementere LocoNet- og CAN-bus-funktionalitet?
Det korte svar er nej. Det lange svar er, at jeg ikke ejer en Z21 eller Z21 XL, derfor har jeg ikke behovet og kan ikke teste funktionaliteten.
Vil du implementere understøttelse af trådløs forbindelse til Z21?
Faktisk – hvis dit netværk er konfigureret korrekt, og du har Roco 10814 eller bruger dit eget access-point, kan du få trådløs adgang til Z21. Mit projekt Z21Dashboard er testet over trådløst LAN, og det virker fint. Nogle gange skulle jeg dog oprette forbindelse mere end én gang.
Hvordan kommer jeg i gang med at skrive min egen applikation?
Tag et kig på Z21Client – særligt Z21Dashboard-applikationen – for at se, hvordan den er implementeret og for inspiration til, hvad du selv kan lave.
Liste over implementerede Z21 LAN Protokol-kommandoer
| Z21 Protocol Command (v1.13) | Implementation Status (Public Method) |
|---|---|
| System, Status & Version | |
| LAN_GET_SERIAL_NUMBER | GetSerialNumberAsync |
| LAN_LOGOFF | DisconnectAsync |
| LAN_X_GET_VERSION | [Not implemented] |
| LAN_X_GET_STATUS | GetSystemStateAsync |
| LAN_X_SET_TRACK_POWER_OFF | SetTrackPowerOffAsync |
| LAN_X_SET_TRACK_POWER_ON | SetTrackPowerOnAsync |
| LAN_X_SET_STOP | SetEmergencyStopAsync |
| LAN_GET_FIRMWARE_VERSION | GetFirmwareVersionAsync |
| LAN_SET_BROADCASTFLAGS | SetBroadcastFlags (Private) |
| LAN_GET_BROADCASTFLAGS | GetBroadcastFlagsAsync |
| LAN_SYSTEMSTATE_GETDATA | GetSystemStateAsync |
| LAN_GET_HWINFO | GetHardwareInfoAsync |
| LAN_GET_CODE | GetZ21CodeAsync |
| Settings | |
| LAN_GET_LOCOMODE | GetLocoModeAsync |
| LAN_SET_LOCOMODE | SetLocoModeAsync |
| LAN_GET_TURNOUTMODE | GetTurnoutModeAsync |
| LAN_SET_TURNOUTMODE | SetTurnoutModeAsync |
| Driving | |
| LAN_X_GET_LOCO_INFO | GetLocoInfoAsync |
| LAN_X_SET_LOCO_DRIVE | SetLocoDriveAsync |
| LAN_X_SET_LOCO_FUNCTION | SetLocoFunctionAsync |
| LAN_X_SET_LOCO_FUNCTION_GROUP | [Not implemented] |
| LAN_X_SET_LOCO_BINARY_STATE | [Not implemented] |
| LAN_X_SET_LOCO_E_STOP | [Not implemented] |
| LAN_X_PURGE_LOCO | [Not implemented] |
| Switching | |
| LAN_X_GET_TURNOUTINFO | GetTurnoutInfoAsync |
| LAN_X_SET_TURNOUT | SetTurnoutPositionAsync |
| LAN_X_GET_TURNOUT_MODE | GetTurnoutModeAsync |
| LAN_X_SET_TURNOUT_MODE | SetTurnoutModeAsync |
| LAN_X_SET_EXT_ACCESSORY | [Not implemented] |
| LAN_X_GET_EXT_ACCESSORY_INFO | [Not implemented] |
| Reading and writeing decoder CVs | |
| LAN_X_CV_READ | GetCVValueFromProgTrackAsync |
| LAN_X_CV_WRITE | SetCVValueOnProgTrackAsync |
| LAN_X_CV_POM_WRITE_BYTE | SetCVValueOnPOMAsync |
| LAN_X_CV_POM_WRITE_BIT | SetCVBitOnPOMAsync |
| LAN_X_CV_POM_READ_BYTE | GetCVValueFromPOMAsync |
| LAN_X_CV_POM_ACCESSORY_WRITE_BYTE | [Not Implemented] |
| LAN_X_CV_POM_ACCESSORY_WRITE_BIT | [Not Implemented] |
| LAN_X_CV_POM_ACCESSORY_READ_BYTE | [Not Implemented] |
| LAN_X_MM_WRITE_BYTE | [Not Implemented] |
| LAN_X_DCC_READ_REGISTER | [Not Implemented] |
| LAN_X_DCC_WRITE_REGISTER | [Not Implemented] |
| Feedback (R-Bus) | |
| LAN_RMBUS_GETDATA | GetRBusDataAsync |
| LAN_RMBUS_PROGRAMMODULE | [Not Implemented] |
| RailCom | |
| LAN_RAILCOM_GETDATA | GetRailComDataAsync / GetNextRailComDataAsync |
| LocoNet | |
| LAN_LOCONET_FROM_LAN | [Not Implemented] |
| LAN_LOCONET_DISPATCH_ADDR | [Not Implemented] |
| LAN_LOCONET_DETECTOR | [Not Implemented] |
| CAN | |
| LAN_CAN_DETECTOR | [Not Implemented] |
| LAN_CAN_DEVICE_GET_DESCRIPTION | [Not Implemented] |
| LAN_CAN_DEVICE_SET_DESCRIPTION | [Not Implemented] |
| LAN_CAN_BOOSTER_SET_TRACKPOWER | [Not Implemented] |
| Fast Clock | |
| LAN_FAST_CLOCK_CONTROL | [Not implemented] |
| LAN_FAST_CLOCK_DATA | [Not implemented] |
| LAN_FAST_CLOCK_SETTINGS_GET | [Not implemented] |
| LAN_FAST_CLOCK_SETTINGS_SET | [Not implemented] |