...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