...wir basteln eine Schnittstelle :-))
Das NENSIS Interface
Doku der Schnittstelle 1.4 zur Kommunikations-Dll
Hier die Kurzdoku der Schnittstelle zur Kommunikationsdll (damit ich
nicht dauernd E-Mails schreiben muss)
...ist eher was für Programmierer ;-))
Vorbemerkungen
Beim Programmstart sucht NENSIS in seinem Heimatverzeichnis (und nur
hier!) nach nensis*.dll Dateien. Wobei davon ausgegangen wird, dass
unter dieser Namensmaske nur Kommunikations-Dlls gefunden werden
können.
Zur Kommunikation im Spielmodus kann nur eine DLL verwendet werden.
Welche, kann ggf. über Bearbeiten/Kommunikationsdatei
festgelegt
werden.
Die verwendete Dll und die Kommunikationskonfiguration werden zusammen
mit dem Gleisplan gespeichert. Sind also projektspezifisch.
Die Dll wird erst bei Bedarf geladen. Die Funktionsadressen werden
über GetProcAddress() ermittelt. Es erfolgt also alles
dynamisch.
Allerdings MUSS eine Kommunikations-Dll bestimmte benannte Funktionen
mit bestimmten Parameterformaten als API bereithalten, damit das alles
funktioniert.
NENSIS spricht zwar nur Funktioen an, für die auch Adressen
ermittelbar sind und versucht ansonsten ohne die speziellen Funktionen
auszukommen, aber funktionell gibt es dann eben entsprechende
Einschränkungen.
NENSIS arbeitet asyncron. Bedeutet: Schaltbefehle und
Rückmeldungen werden getrennt und zeitlich unabhängig
behandelt.
Rückmeldungen werden auch unabhängig von vorher
abgesetzten
Schaltbefehlen bearbeitet. Es wird dadurch auch z.B. ein gleichzeitiger
Betrieb von Computersteuerung, Steuerung durch Gleisbildstellpult und
rein manueller Steuerung möglich.
erwartete API Funktionen einer
Dll
DWORD __stdcall getData(LPVOID pData,
DWORD len);
bool __stdcall setData(LPVOID pData,
DWORD len);
bool __stdcall goOn(FARPROC pRcvFunc,
LPWORD pAddressArray,
WORD numAdresses
);
bool __stdcall goOff(void);
void __stdcall configIt(HWND
parent=0);
bool __stdcall resetDev(void);
bool __stdcall send2(WORD command);
bool __stdcall cancelSend2(WORD command);
int __stdcall getStatus(int question);
von NENSIS für
Rückrufe zur Verfügung gestellte
Funktion
void __stdcall getDllMessage(WORD command);
Wird NICHT exportiert! Weiteres siehe unten.
DWORD
__stdcall getData(LPVOID pData,
DWORD len);
Wenn NENSIS einen Gleisplan speichert UND! eine CommDll vorhanden ist
bzw. bei mehreren vorhandenen eine ausgewählt ist wird dieser
Aufruf an die Dll abgesetzt, um ggf. Daten der Dll mit zu speicher.
pData
enthält einen
Pointer auf einen Speicherblock mit der Grösse von len
Byte. Im Rückgabewert wird
die Anzahl der geschriebenen Bytes der Dll erwartet.
Nicht einen neuen Pointer zurückliefern, sondern die Daten in
den
bereitgestellten Übergabebuffer kopieren und die
Grösse des
tatsächlichen Datenblocks in Byte als Rückgabewert an
NENSIS
geben. Ist der Buffer zu klein, einfach die benötigte
Grösse
zurückgeben. NENSIS prüft es ab und wiederholt ggf.
den
Aufruf mit entsprechend vergrössertem Übergabebuffer.
Denke dran: strcpy(pChar1,pChar2); kopiert strlen(pChar2)+1; Bytes.
Wenn len == strlen(pChar2); ist und das einfach kopiert wird, wird
irgendwas nicht reserviertes übermarmelt. Das kann zwar 1000
Mal
gutgehen, aber irgendwann crashed es bestimmt.
bool __stdcall setData(LPVOID pData,
DWORD len);
Wenn Daten geladen werden und/oder in den Spielbetrieb gewechselt wird,
übermittelt NENSIS mit dieser Funktion Einstellungsdaten an
die
Dll, sofern welche in der Gleisplandatei vorhanden waren.
pData
ist ein Pointer auf
einen Datenblock der Länge len
Bytes.
Die Dll MUSS die Daten umkopieren, da der für die
Übergabe
verwendete Speicherblock von NENSIS nur für den Transfer
reserviert und wieder freigegeben wird. Also: nicht einfach den Pointer
merken, sonder z.B. mit CopyMemory() arbeiten ;-)
Es ist sinnvoll, in den Datenblock von seiten der Dll einen ID-String
einzubauen, damit die Dll sicherstellen kann, dass die Daten auch im
richtigen Format vorliegen. NENSIS kann sich darum nicht
kümmern
und schiebt die Daten einfach durch.
bool
__stdcall goOn(FARPROC pRcvFunc,
LPWORD pAddressArray,
WORD numAddresses);
Wird von NENSIS abgesetzt, wenn im Spielbetrieb auf 'ON' geschaltet
wird.
pRcvFunc
enthält einen
Pointer auf die Rückruffunktion void __stdcall
getDllMessage(WORD
command);
pAddressArray
ist ein Pointer
auf ein Array mit den verwendeten Adressen. Format wie command.
numAddresses enthält
die Anzahl der Adressen im Array pAddrssArray.
Rückgabe true bei
erfolgreichem 'goOnline' anderenfalls
false.
bool
__stdcall goOff(void);
Wird von NENSIS abgesetzt, wenn im Spielbetrieb auf 'OFF' geschaltet
wird.
Rückgabe true bei erfolgreichem 'goOffline' anderenfalls
false.
void
__stdcall configIt(HWND parent=0);
Wird abgesetzt, wenn der Anwender den Menübefehl
Bearbeiten/Konfiguration Komminikationsmodul auswählt.
kann von der Dll genutzt werden ... oder auch nicht.
Kann auch für die Öffnung eines erweiterten Dialogs
mit
Statusinfos usw. der Dll genutzt werden.
bool
__stdcall resetDev(void);
Wird beim (neuerlichen) Wechsel in den Spielmodus und bei bestimmten
internen 'Ungereimtheiten' aufgerufen.
Rückgabe true, wenn erfolgreich, anderenfalls false.
bool
__stdcall send2(WORD command);
übermittelt einen Schaltbefehl. Format von command
siehe unten.
Die Dll sollte den Schaltbefehl abnehmen und in einer Warteschlange
zwischenspeicher. Besonders beim Ausführen von
grösseren
Fahrstrassenbatches können relativ schnell hintereinander
mehrere
send2()-Befehle folgen.
Rückgabe sollte true sein, wenn der Befehl angenommen wurde.
false, wenn er zurückgewiesen wird.
bool
__stdcall cancelSend2(WORD command);
Widerruf des Kommandos command. Es muss nicht unbedingt das letzte command
sein.
Rückgabe true, wenn erfolgreich, anderenfalls false.
int
__stdcall getStatus(int question);
Abfrage des Statusses des Kommunikationsmodules.
question
wird noch nicht
genutzt und ist zur Zeit immer 0.
Bisher definierte Rückgabewerte:
0 = alles OK, Modul offline
1 = konnte nicht online schalten
50 - 59 = alles OK, Modul auf (nn-50) Kanälen online,
Warteschlange leer
>100 = Modul online, nnn Befehle in der Warteschlange
NENSIS Rückruffunktion
void __stdcall getDllMessage(WORD command);
Der Funktionspointer dieser
Rückruffunktion wird der Dll mit
goOn() übergeben.
Statusmeldungen der Magnetartikel können über diese
Funktion
an NENSIS geleitet werden.
Sind sie gültig, wird NENSIS es entsprechend visualisieren.
Format von command
siehe
weiter unten.
Format
von WORD command
- LOBYTE Bit 0 und 1: Schalte
Leitung bzw. Status der
Schaltleitung. Gültig ist eigentlich nur dez(1) und dez(2).
Bit 0 ist der Leitung 'Weiche gerade', Bit 1 der Leitung 'Weiche
abzweigend' zugeordnet.
- LOBYTE Bit 2 bis 7: Adresse.
dez(0) bedeutet aus.
- HIBYTE Bit 0 bis 3: Kanal.
dez(0) bedeutet aus. Zur Zeit
unterstützt: dez(0) bis dez(9).
- HIBYTE Bit 4 bis 7:
reserviert, muss dez(0) sein.