I/O Fahrpultsoftware für C++
-
- Beiträge: 82
- Registriert: 22.01.2007 18:01:17
- Wohnort: Nürnberg
I/O Fahrpultsoftware für C++
Nachdem ich meinen Schwager ein bisschen beschwatzt habe, werden wir eine I/O Karte selbst aufbauen.
Grundlage ist einen PIC18F2550 samt Ansteuerung über USB.
Hardwareseitig wird es keine Probleme geben. Er ist Elektronik/Mechatronic Ing.
Softwareseitig sieht es schon magerer aus
Deshalb der Aufruf, ob jemand uns den Quellcode von einer Fahrpultsoftware für C++ geben kann. Weil gerade das Einbinden des TCP-Protokoll doch Probleme für uns darstellt.
Grüsse Andreas (der wohl wieder Haare beim Löten lassen muss, weil alles was größer als 0805 ist, nicht auf die Platine kommt )
Grundlage ist einen PIC18F2550 samt Ansteuerung über USB.
Hardwareseitig wird es keine Probleme geben. Er ist Elektronik/Mechatronic Ing.
Softwareseitig sieht es schon magerer aus
Deshalb der Aufruf, ob jemand uns den Quellcode von einer Fahrpultsoftware für C++ geben kann. Weil gerade das Einbinden des TCP-Protokoll doch Probleme für uns darstellt.
Grüsse Andreas (der wohl wieder Haare beim Löten lassen muss, weil alles was größer als 0805 ist, nicht auf die Platine kommt )
Zuletzt geändert von Andreas K. am 17.02.2010 22:05:51, insgesamt 1-mal geändert.
-
- Beiträge: 4718
- Registriert: 28.04.2002 12:56:00
- Kontaktdaten:
Re: I/O Fahrpultsoftware für C++
In C# habe ich vor einiger Zeit eine (meiner Meinung nach) recht handliche Bibliothek geschrieben. Ich bin mir nicht sicher, ob man solche DLLs auch in C++ irgendwie einbinden kann. Müsste aber doch eigentlich gehen - Roland Ziegler weiß doch da bestimmt Bescheid.
-
- Beiträge: 300
- Registriert: 06.05.2009 10:59:49
- Wohnort: Freiberg(Sachs)
Re: I/O Fahrpultsoftware für C++
Verdammt!! Sowas hatte ich doch auch vor!
Ich experimentiere z.Z in C++ und MFC mit einer Fahrpultansteuerung auf Basis der Konkurrenz (Atmel).
Allerdings kann ich mich erst nach diesem Wochenende intensiver damit befassen.
PS: Ich glaube nicht, dass das mit dem C# geht, da C# managed Code ist (also so ne art Interpretersprache so ähnlich wie bei Java). Zudem ist C# dadurch ca. 10mal langsamer als C++ ...
Ich experimentiere z.Z in C++ und MFC mit einer Fahrpultansteuerung auf Basis der Konkurrenz (Atmel).
Allerdings kann ich mich erst nach diesem Wochenende intensiver damit befassen.
PS: Ich glaube nicht, dass das mit dem C# geht, da C# managed Code ist (also so ne art Interpretersprache so ähnlich wie bei Java). Zudem ist C# dadurch ca. 10mal langsamer als C++ ...
Zuletzt geändert von protonmw (Marc) am 18.02.2010 14:19:47, insgesamt 2-mal geändert.
MfG Marc
"Wir genießen das Leben in vollen Zügen!"
"Wir genießen das Leben in vollen Zügen!"
-
- Beiträge: 82
- Registriert: 22.01.2007 18:01:17
- Wohnort: Nürnberg
Re: I/O Fahrpultsoftware für C++
@ protonmw:
Dann lass Dich dabei mal nicht stören!
Uns würde ja nur der allgemeine Teil interessieren.
Also:
Anmelden am TCP Server
Anfrage der Daten
Empfangen der Daten
etc.
Das Einbinden der notwendigen DLL wird sich ja immer unterscheiden.
Von Karte zu Karte.
Schreibst Du die USB Routine selber oder greifst Du auf eine fertige zurück?
Und sprichst Du die Karte über DLL oder einen virtuellen Port?
MfG Andreas
Dann lass Dich dabei mal nicht stören!
Uns würde ja nur der allgemeine Teil interessieren.
Also:
Anmelden am TCP Server
Anfrage der Daten
Empfangen der Daten
etc.
Das Einbinden der notwendigen DLL wird sich ja immer unterscheiden.
Von Karte zu Karte.
Schreibst Du die USB Routine selber oder greifst Du auf eine fertige zurück?
Und sprichst Du die Karte über DLL oder einen virtuellen Port?
MfG Andreas
-
- Beiträge: 300
- Registriert: 06.05.2009 10:59:49
- Wohnort: Freiberg(Sachs)
Re: I/O Fahrpultsoftware für C++
Nix mit USB!
Ich wollte mit der Leuchtmelderzeile beginnen, wo z.B. PZB, Sifa und Türen angezeigt werden. Dazu (versuche) ich die entsprechenden Daten aus Zusi zu lesen (via TCP Server). Die Daten sollen dann über die RS232 ausgegeben werden. Warum RS232? Nun, die ist zwar alt aber einfach!
Als Hardware ist ein RS485 Bus gedacht, an dem dann ATtiny2313'er dran hängen und die LEDs ansteuern. Später dann auch Servos für den Tacho, die Luft usw...
MfG Marc
Ich wollte mit der Leuchtmelderzeile beginnen, wo z.B. PZB, Sifa und Türen angezeigt werden. Dazu (versuche) ich die entsprechenden Daten aus Zusi zu lesen (via TCP Server). Die Daten sollen dann über die RS232 ausgegeben werden. Warum RS232? Nun, die ist zwar alt aber einfach!
Als Hardware ist ein RS485 Bus gedacht, an dem dann ATtiny2313'er dran hängen und die LEDs ansteuern. Später dann auch Servos für den Tacho, die Luft usw...
MfG Marc
MfG Marc
"Wir genießen das Leben in vollen Zügen!"
"Wir genießen das Leben in vollen Zügen!"
-
- Beiträge: 82
- Registriert: 22.01.2007 18:01:17
- Wohnort: Nürnberg
Re: I/O Fahrpultsoftware für C++
Das kommt mir bekannt vor.
Ansteuerung von:
Leuchtmelder
PWM für Tacho
Servo oder Schrittmotoren für Manometer
Wir werden aber über USB gehen.
Aber nach der Dokumentation kann man das Board über einen virtuell Port als RS232 ansteuern.
MfG Andreas
Ansteuerung von:
Leuchtmelder
PWM für Tacho
Servo oder Schrittmotoren für Manometer
Wir werden aber über USB gehen.
Aber nach der Dokumentation kann man das Board über einen virtuell Port als RS232 ansteuern.
MfG Andreas
-
- Beiträge: 300
- Registriert: 06.05.2009 10:59:49
- Wohnort: Freiberg(Sachs)
Re: I/O Fahrpultsoftware für C++
AHA!!Andreas K. hat geschrieben:Aber nach der Dokumentation kann man das Board über einen virtuell Port als RS232 ansteuern.
MfG Marc
"Wir genießen das Leben in vollen Zügen!"
"Wir genießen das Leben in vollen Zügen!"
-
- Beiträge: 82
- Registriert: 22.01.2007 18:01:17
- Wohnort: Nürnberg
Re: I/O Fahrpultsoftware für C++
Mein Schwager kann auch Atmel brennen
- Roland Ziegler
- Beiträge: 5508
- Registriert: 04.11.2001 22:09:26
- Wohnort: 32U 0294406 5629020
- Kontaktdaten:
Re: I/O Fahrpultsoftware für C++
Geht, aber nur über Umweg. Eine Möglichkeit ist COM, und damit auf die Windows-Plattform beschränkt. Eine andere ist CORBA, somit auch zwischen Prozessen. (Umgekehrt, Einbinden von C++ in .Net, ist deutlich einfacher, sogar ohne C++/CLI oder Managed C++.)Andreas Karg hat geschrieben:In C# habe ich vor einiger Zeit eine (meiner Meinung nach) recht handliche Bibliothek geschrieben. Ich bin mir nicht sicher, ob man solche DLLs auch in C++ irgendwie einbinden kann. Müsste aber doch eigentlich gehen - Roland Ziegler weiß doch da bestimmt Bescheid.
Nur - auf einem Micro-Controller hat man doch üblicherweise keine volle Betriebsystemumgebung. Allerdings gibt es ja heutzutage diverse Kästchen, auf denen die mobilen oder Micro-Editionen einer Java- oder .Net-Plattform zu installieren sind.
Wenn das alles nicht gilt, stattdessen C oder C++ mit klassischem Cross-Compiler genutzt werden soll (C++ erfordert zusätzlich einen Calling-Standard, denn in nativem ausführbaren Code gibt es keine OO), dann bleibt die Frage, auf welchem API man denn da aufsetzen kann. Berkeley Sockets würde ich mir vorstellen. Multithreading spielt natürlich auch wieder eine Rolle (ich gehe mal vom entsprechenden Kernel aus). Man braucht also auch ein IPC-API, mit Thread- und Verriegelungs-Funktionen.
Implementieren würde man dann analog zu dem Vorschlag in C#. Das "Pattern", also die Vorgehensweise, ist ja identisch.
-
- Beiträge: 82
- Registriert: 22.01.2007 18:01:17
- Wohnort: Nürnberg
Re: I/O Fahrpultsoftware für C++
@ Roland
Den Artikel werde ich unkommentiert an meinen Schwager weiterleiten!
MfG Andreas
Den Artikel werde ich unkommentiert an meinen Schwager weiterleiten!
MfG Andreas
-
- Beiträge: 300
- Registriert: 06.05.2009 10:59:49
- Wohnort: Freiberg(Sachs)
Re: I/O Fahrpultsoftware für C++
Roland, du hast das missverstanden!
nicht auf den µC soll das Programm sondern auf den PC...
EDIT: Um sowas auf nen µC zu bringen brauchts dann schon nen 32bit ARM oder ähnliches
nicht auf den µC soll das Programm sondern auf den PC...
EDIT: Um sowas auf nen µC zu bringen brauchts dann schon nen 32bit ARM oder ähnliches
Zuletzt geändert von protonmw (Marc) am 18.02.2010 18:38:01, insgesamt 2-mal geändert.
MfG Marc
"Wir genießen das Leben in vollen Zügen!"
"Wir genießen das Leben in vollen Zügen!"
- Roland Ziegler
- Beiträge: 5508
- Registriert: 04.11.2001 22:09:26
- Wohnort: 32U 0294406 5629020
- Kontaktdaten:
Re: I/O Fahrpultsoftware für C++
Ich hab bei mir etwas "quick and dirty"-Code für Windows gefunden, ist eine Mischung aus C und (prozeduraler) C++-Notation. "Windows"-spezifisch scheint aber aber nur das Include des Winsock-API, was sich von original Berkeley nur in Nuancen unterscheidet. Ich weiß auch nicht mehr, welche Anteile von mir sind. #define für Konstanten benutze ich eigentlich seit 15 Jahren nicht mehr. Ich stelle das mal hier ein, ohne jede Gewähr. Und ich hoffe, dass keine Rechter Dritter verletzt werden. Bitte, bitte nicht als Ersatz für eine gescheite OO-Implementierung nehmen. Ich vermute, es ging damals nur um einen "Gangbarkeitsversuch", aufbauend auf zugeliefertem Code-Fragment. Das Ergebnis zeigt den Umgang mit den Sockets in C/C++, und den grundsätzlichen Kommunikationsaufbau. Mehr nicht.
Nach all den "Disclaimern" hier der Code:
Nach all den "Disclaimern" hier der Code:
Code: Alles auswählen
#include <stdio.h>
#include <time.h>
#include "winsock2.h"
//--------------------------------------------
// protocol version
#define VERSION 2
//--------------------------------------------
// commands
#define HELLO 1
#define ACK_HELLO 2
#define NEEDED_DATA 3
#define ACK_NEEDED_DATA 4
#define DATA 0x0a
//--------------------------------------------
// sub-commands
#define DATA_CTRLSTAND 0x0a
#define DATA_FINAL 0
//--------------------------------------------
// id for control stand client
#define CLIENT_CTRLSTAND 2
//--------------------------------------------
// data value ids
#define KEINE_FUNKTION 0
#define GESCHWINDIGKEIT 1
#define DRUCK_HAUPTLUFTLEITUNG 2
#define DRUCK_BREMSZYLINDER 3
#define DRUCK_HAUPTLUFTBEHAELTER 4
#define ZUGKRAFT_GESAMT 5
#define ZUGKRAFT_PRO_ACHSE 6
#define STROM 7
#define SPANNUNG 8
#define MOTORDREHZAHL 9
#define UHRZEIT_STUNDE 10
#define UHRZEIT_MINUTE 11
#define UHRZEIT_SEKUNDE 12
#define LZB_ZIEL_GESCHWINDIGKEIT 13
#define LZB_AFB_SOLL_GESCHWINDIGKEIT 14
#define LZB_ZIELWEG 15
#define FAHRSTUFE 16
#define FENSTER_3D 17
#define AFB_SOLL_GESCHWINDIGKEIT 18
#define DRUCK_HILFSLUFTBEHAELTER 19
#define LM_PZB_1000HZ 20
#define LM_PZB_500HZ 21
#define LM_PZB_BEFEHL 22
#define LM_PZB_ZUGART_U 23
#define LM_PZB_ZUGART_M 24
#define LM_PZB_ZUGART_O 25
#define LM_LZB_H 26
#define LM_LZB_G 27
#define LM_LZB_E40 28
#define LM_LZB_EL 29
#define LM_LZB_ENDE 30
#define LM_LZB_V40 31
#define LM_LZB_B 32
#define LM_LZB_S 33
#define LM_LZB_U 34
#define LM_LZB_PRUEFEN 35
#define LM_SIFA 36
#define LM_HAUPTSCHALTER 37
#define LM_GETRIEBE 38
#define LM_SCHLEUDERN 39
#define LM_GLEITEN 40
#define LM_MG_BREMSE 41
#define LM_H_BREMSE 42
#define LM_R_BREMSE 43
#define LM_HOCHABBREMSUNG 44
#define LM_SCHNELLBREMSUNG 45
#define LM_NOTBREMSUNG 46
#define LM_TUEREN 47
#define LM_TFZ_NUMMER 48
#define LM_MAX_TFZ_GESCHWINDIDIGKEIT 49
#define LM_UHRZEIT 50 // TDateTime, 8 Byte
#define SCHALTER_FAHRSTUFEN 51
#define SCHALTER_FUEHRERBREMSVENTIL 52
#define SCHALTER_DYN BREMSE 53
#define SCHALTER_ZUSATZBREMSE 54
#define SCHALTER_AFB_GESCHWINDIGKEIT 55
#define SCHALTER_AFB_EIN_AUS 56
#define SCHALTER_MG_BREMSE 57
#define SCHALTER_PZB_WACHSAM 58
#define SCHALTER_PZB_FREI 59
#define SCHALTER_PZB_BEFEHL 60
#define SCHALTER_SIFA 61
#define SCHALTER_HAUPTSCHALTER 62
#define SCHALTER_MOTOR_EIN_AUS 63
#define SCHALTER_FAHRTRICHTUNG 64
#define SCHALTER_PFEIFE 65
#define SCHALTER_SANDEN 66
#define SCHALTER_TUEREN 67
#define SCHALTER_GLOCKE 68
#define SCHALTER_LOKBREMSE_ENTLUEFTEN 69
#define SCHALTER_SCHLEUDERSCHUTZBREMSE 70
#define LM_DREHZAHLVERSTELLUNG 71
#define LM_FAHRTRICHTUNG_VOR 72
#define LM_FAHRTRICHTUNG_ZURUECK 73
#define SCHALTER_SIGNUM 74
#define LM_LZB_ZIELWEG_AB_0 75
#define LZB SOLL_GESCHWINDIGKEIT 76
#define LM_BLOCK_BIS_ZU_DEM_DIE_STRECKE_FREI_IST 77 // String
#define SCHALTER_LUEFTER 78
#define LM_GNT_G 79
#define LM_GNT_U 80
#define LM_GNT_B 81
#define LM_GNT_S 82
#define HINTERGRUNDBILD 83
#define PLATZHALTER_NACHTINSTRUMENT 84
#define STRECKEN_KM 85
#define TUEREN 86
#define AUTOPILOT 87
#define REISEZUG 88
#define PZB_SYSTEM 89
#define FRAMES_PER_SECOND 90
#define FUEHRERSTAND_SICHTBAR 91
#define NAECHSTER_BLOCKNAME 92 // String
#define NAECHSTES_GLEIS 93 // String
#define BREMSHUNDERTSTEL 94
#define BREMSSTELLUNG 95
#define ZUGDATEI 96 // String
//--------------------------------------------
// a string in delphi
// no 0-termination !
#pragma pack (1)
struct DelphiString {
unsigned char length;
unsigned char string [255];
};
#pragma pack ()
//--------------------------------------------
// union for data value types returned
union DataValues {
DelphiString valString;
double valDateTime;
float valFloat;
};
//--------------------------------------------
// get the length of a value data field
int getDataValLen (unsigned char idData, DataValues * pVal) {
int len;
len = 0;
switch (idData) {
default:
len = sizeof(float);
break;
case LM_BLOCK_BIS_ZU_DEM_DIE_STRECKE_FREI_IST:
case NAECHSTER_BLOCKNAME:
case NAECHSTES_GLEIS:
case ZUGDATEI:
if (!pVal)
break;
len = pVal->valString.length + 1;
break;
case LM_UHRZEIT:
len = sizeof (double);
break;
}
return len;
}
//--------------------------------------------
// send a datagram, executable function
int sendDatagramExe (SOCKET * pSock, unsigned short int cmd, unsigned short int * pSubCmd, char * data, int datalen) {
// long int assumed as 4 byte
unsigned long int len;
int bytesSent;
unsigned short int ncmd;
unsigned short int nsubcmd;
// network byte order
ncmd = htons (cmd);
len = datalen + 2; // sizeof (short int);
if (pSubCmd) {
len += 2;
nsubcmd = htons (*pSubCmd);
}
//no need to send TCP datagrams in one go
//TCP will pack automatically
//datagram len
bytesSent = send(*pSock, (char*)&len, 4, 0 );
if (bytesSent != 4)
return -1;
// datagram command
bytesSent = send(*pSock, (char*)&ncmd, 2, 0 );
if (bytesSent != 2)
return -1;
// datagram sub command
if (pSubCmd) {
bytesSent = send(*pSock, (char*)&nsubcmd, 2, 0 );
if (bytesSent != 2)
return -1;
}
// datagram data
if (datalen > 0) {
bytesSent = send(*pSock, data, datalen, 0 );
if (bytesSent != datalen)
return -1;
}
printf( "Command %d sent, total length = %d\n", cmd, len );
return 0;
}
//--------------------------------------------
// send a datagram, wrapper for calls w/o sub-command
int sendDatagram (SOCKET * pSock, unsigned short int cmd, char * data, int datalen) {
return sendDatagramExe (pSock, cmd, 0, data, datalen);
}
//--------------------------------------------
// receive a datagram, incl. basic checks
int receiveDatagram (SOCKET * pSock, unsigned short int * pCmd, char* pData, int* pDatalen) {
long int len;
long int datalen;
int bytesRecv;
unsigned short int ncmd;
// receive header
bytesRecv = recv( *pSock, (char*)&len, 4, 0 );
if (bytesRecv != 4)
return -1;
if (len <= 2 || !pCmd)
return -1;
// receive command
bytesRecv = recv( *pSock, (char*)&ncmd, 2, 0 );
if (bytesRecv != 2)
return -1;
*pCmd = ntohs (ncmd);
datalen = len - 2;
if (datalen > *pDatalen)
return -1;
// receive data
bytesRecv = recv( *pSock, pData, datalen, 0 );
if (bytesRecv != datalen)
return -1;
*pDatalen = datalen;
return 0;
}
//--------------------------------------------
// send & receive HELLO datagram
// client name hard coded in demo
int primitiveHello (SOCKET * pSock) {
char helloData[] = {VERSION, CLIENT_CTRLSTAND, 4, 'D', 'e', 'm', 'o'};
unsigned short int cmd;
int result;
char replyData;
int replySize;
cmd = HELLO;
result = sendDatagram (pSock, cmd, helloData, sizeof(helloData));
if (result < 0)
return -1;
replySize = sizeof(replyData);
result = receiveDatagram (pSock, &cmd, &replyData, &replySize);
if (result < 0)
return -1;
if (cmd != ACK_HELLO || replyData != 0)
return -1;
printf( "\"Hello\" primitive completed.\n" );
return 0;
}
//--------------------------------------------
// send & receive NEEDED_DATA datagram, executable function
int primitiveDataExe (SOCKET * pSock, unsigned short int dataCmd, unsigned char * idData, int idDatalen) {
int result;
char replyData;
int replySize;
unsigned short int cmd;
cmd = NEEDED_DATA;
result = sendDatagramExe (pSock, cmd, &dataCmd, (char*)idData, idDatalen);
if (result < 0)
return -1;
replySize = sizeof(replyData);
result = receiveDatagram (pSock, &cmd, &replyData, &replySize);
if (result < 0)
return -1;
if (cmd != ACK_NEEDED_DATA || replyData != 0)
return -1;
return 0;
}
//--------------------------------------------
// send & receive NEEDED_DATA datagram, wrapper for actual subscription
int primitiveData (SOCKET * pSock, unsigned char * idData, int idDatalen) {
int result;
result = primitiveDataExe (pSock, DATA_CTRLSTAND, idData, idDatalen);
if (result < 0)
return -1;
printf( "\"Needed Data\" primitive completed.\n" );
return 0;
}
//--------------------------------------------
// send & receive NEEDED_DATA datagram, wrapper for terminator
int primitiveDataFinal (SOCKET * pSock) {
int result;
result = primitiveDataExe (pSock, DATA_FINAL, 0, 0);
printf( "\"Needed Data Final\" primitive completed.\n" );
return 0;
}
//--------------------------------------------
// connect to server, address hard coded to local in demo
int connectServer (SOCKET * pSock) {
// Initialize Winsock.
WSADATA wsaData;
int iResult = WSAStartup( MAKEWORD(2,2), &wsaData );
if ( iResult != NO_ERROR )
printf("Error at WSAStartup()\n");
// Create a socket.
*pSock = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP );
if ( *pSock == INVALID_SOCKET ) {
printf( "Error at socket(): %ld\n", WSAGetLastError() );
WSACleanup();
return -1;
}
// Connect to a server.
sockaddr_in clientService;
clientService.sin_family = AF_INET;
clientService.sin_addr.s_addr = inet_addr( "127.0.0.1" );
//clientService.sin_addr.s_addr = inet_addr( "192.168.0.2" );
clientService.sin_port = htons( 1435 );
if ( connect( *pSock, (SOCKADDR*) &clientService, sizeof(clientService) ) == SOCKET_ERROR) {
printf( "Failed to connect.\n" );
WSACleanup();
return -1;
}
printf( "Connected.\n" );
return 0;
}
//--------------------------------------------
// init a session
int initSession (SOCKET * pSock) {
int result;
// send HELLO
result = primitiveHello (pSock);
if (result < 0)
return -1;
// IDs for subscription
unsigned char neededData[] = {
GESCHWINDIGKEIT,
LM_PZB_1000HZ,
LM_PZB_500HZ,
LM_UHRZEIT,
NAECHSTER_BLOCKNAME,
ZUGDATEI
};
// send NEEDED_DATA
result = primitiveData (pSock, neededData, sizeof(neededData));
if (result < 0)
return -1;
// finish
result = primitiveDataFinal (pSock);
if (result < 0)
return -1;
printf( "Session initialized.\n" );
return 0;
}
//--------------------------------------------
// handling unknown IDs
void handleDataDefault (unsigned char idData) {
printf ("Data id = %d\n", idData);
}
//--------------------------------------------
// sample of handling float value (single precision)
void handleDataFloat (unsigned char idData, float val) {
printf ("Data id = %d, float val = %5.1f\n", idData, val);
}
//--------------------------------------------
// sample of handling bool value
void handleDataBool (unsigned char idData, float val) {
int boolVal = val == 1;
printf ("Data id = %d, bool val = %d\n", idData, boolVal);
}
//--------------------------------------------
// month lengths for handling Delphi format
int MonthLength [] = {31,28,31, 30,31,30, 31,31,30, 31,30,31};
//--------------------------------------------
// sample of handling weird Delphi date & time format
void handleDataTime (unsigned char idData, double val) {
// lep years w/ century exceptions
double OneYearInDays = 365.25;
// days is integral part of value
int days = (int)val;
// time of day is fractional part of val
double time = val - days;
// simplified handling of century exception
if (days > 100 * OneYearInDays)
days --;
int year = (int)(days / OneYearInDays);
days -= (int)(year * OneYearInDays);
year = year + 1900;
int leapyear = year % 4 == 0;
int leapyear100 = year % 100 == 0;
int leapyear400 = year % 400 == 0;
leapyear = leapyear && (!leapyear100 || leapyear400);
if (leapyear)
MonthLength[1] = 29;
else
MonthLength[1] = 28;
int idx = 0;
while (idx <= 11 && MonthLength[idx] <= days) {
days -= MonthLength[idx];
idx++;
}
int month = idx + 1;
// time of day in secs
int secs = (int)(time * 3600 * 24);
int hour = secs / 3600;
secs = secs % 3600;
int min = secs / 60;
secs = secs % 60;
tm tim;
tim.tm_year = year - 1900;
tim.tm_mon = month - 1;
tim.tm_mday = days;
tim.tm_hour = hour;
tim.tm_min = min;
tim.tm_sec = secs;
tim.tm_isdst = 0;
char timstr [32];
strftime (timstr, 32, "%d.%m.%Y %H:%M:%S", &tim);
printf ("Data id = %d, date/time val = %s\n", idData, timstr);
}
//--------------------------------------------
void handleDataString (unsigned char idData, DelphiString * pVal) {
pVal->string[pVal->length] = 0;
printf ("Data id = %d, string val = \"%s\"\n", idData, pVal->string);
}
//--------------------------------------------
// receiving and processing data values from server
int receiveData (SOCKET * pSock) {
char buf [2048];
int result;
unsigned short int cmd;
char idData;
DataValues * pDataValues;
int datalen;
int idx;
datalen = 2048;
result = receiveDatagram (pSock, &cmd, buf, &datalen);
if (result < 0)
return -1;
if (cmd != DATA)
return -1;
// data body may contain more than one value
idx = 0;
while (idx < datalen) {
idData = buf[idx++];
pDataValues = (DataValues*)&buf[idx];
idx += getDataValLen (idData, pDataValues);
switch (idData) {
default:
handleDataDefault (idData);
break;
case GESCHWINDIGKEIT:
handleDataFloat (idData, pDataValues->valFloat);
break;
case LM_PZB_1000HZ:
case LM_PZB_500HZ:
handleDataBool (idData, pDataValues->valFloat);
break;
case LM_UHRZEIT:
handleDataTime (idData, pDataValues->valDateTime);
break;
case NAECHSTER_BLOCKNAME:
case ZUGDATEI:
handleDataString (idData, &pDataValues->valString);
break;
}
}
return 0;
}
//--------------------------------------------
// main function of demo program
int main(int, char**) {
SOCKET sock;
int result;
result = connectServer (&sock);
if (result < 0)
return 0;
result = initSession (&sock);
if (result < 0)
return 0;
printf( "Entering endless data loop. Ctrl/C to abort.\n" );
while (result == 0)
result = receiveData (&sock);
return 1;
}
-
- Beiträge: 4718
- Registriert: 28.04.2002 12:56:00
- Kontaktdaten:
Re: I/O Fahrpultsoftware für C++
Bissi viel blöde Tipparbeit, die 1000 #defines. Ich hab's mir damals etwas leichter anders aufwändig gemacht und die Originaldatei vom TCP-Server in eine Liste eingelesen, die ich wiederum in serialisierter Form als Ressource in meine DLL eingebunden habe. Ist eigentlich ziemlich wenig Arbeit, wenn man mal rausgefunden hat, wie's geht. Letzteres war der größte Aufwand, aber ich will ja schließlich was dazulernen.
- Roland Ziegler
- Beiträge: 5508
- Registriert: 04.11.2001 22:09:26
- Wohnort: 32U 0294406 5629020
- Kontaktdaten:
Re: I/O Fahrpultsoftware für C++
Aus den #defines in C sollten in C++ enum-Werte werden. Lässt sich mit jedem besseren Text-Editor recht zügig umsetzen ohne alles neu zu tippen. Deswegen war ich ja etwas irritiert, als ich dieses Teil gefunden hatte und rein schaute. Ohne enums (bzw C-#defines) würden die Switch-Cases nicht funktionieren, denn die brauchen feste Werte zur Compile-Zeit.
Es ist immer die Frage, wie groß man den Aufwand treibt. Bei einer überschaubaren und mittelfristig stabilen Schnittstelle würde ich zur festen Codierung der Telegrammauswertung raten. Wobei man im professionelleren Ansatz die Socket-Ebene von der Telegrammebene natürlich komplett trennt. (Hatte ich vermutlich auch für C# vorgeschlagen.)
Es ist immer die Frage, wie groß man den Aufwand treibt. Bei einer überschaubaren und mittelfristig stabilen Schnittstelle würde ich zur festen Codierung der Telegrammauswertung raten. Wobei man im professionelleren Ansatz die Socket-Ebene von der Telegrammebene natürlich komplett trennt. (Hatte ich vermutlich auch für C# vorgeschlagen.)
-
- Beiträge: 4718
- Registriert: 28.04.2002 12:56:00
- Kontaktdaten:
Re: I/O Fahrpultsoftware für C++
Die Liste der Messgrößen ist bei mir auch eine reine Komfortfunktion für den Benutzer der DLL. Man braucht nicht die Größe Nummer siebenundvierzigeinhalb anfordern, sondern kann bequem den Namen als Klartext anfordern. Außerdem brauchte ich die Liste sowieso, weil in der der Datentyp der Größe definiert ist. Stichwort Typsicherheit und so für den Anwender.
-
- Beiträge: 82
- Registriert: 22.01.2007 18:01:17
- Wohnort: Nürnberg
Re: I/O Fahrpultsoftware für C++
@ Roland:
Sieht ja recht "vernünftig" aus.
Da aber meine Programmierkenntnisse auf dem Turbo Pascal aus meiner Zeit vom Gymnasium baut, werde ich es einfach meinen persönlichen Entwicklungsingenieur vorlegen.
Hab ich schon gesagt, dass das Turbo Pascal noch von 5,25″-Diskette zum booten war!
Oh Gott, bin ich alt!
MfG Andreas
Sieht ja recht "vernünftig" aus.
Da aber meine Programmierkenntnisse auf dem Turbo Pascal aus meiner Zeit vom Gymnasium baut, werde ich es einfach meinen persönlichen Entwicklungsingenieur vorlegen.
Hab ich schon gesagt, dass das Turbo Pascal noch von 5,25″-Diskette zum booten war!
Oh Gott, bin ich alt!
MfG Andreas
- Roland Ziegler
- Beiträge: 5508
- Registriert: 04.11.2001 22:09:26
- Wohnort: 32U 0294406 5629020
- Kontaktdaten:
Re: I/O Fahrpultsoftware für C++
In der Schule hatten wir dieses Modell: http://en.wikipedia.org/wiki/Programma_101" target="_blank, war schon etwas betagt.
-
- Beiträge: 82
- Registriert: 22.01.2007 18:01:17
- Wohnort: Nürnberg
Re: I/O Fahrpultsoftware für C++
Dann waren unsere 386 ja richtige Highend Geräte.
Aber lassen wir das, sonst kommt man ja noch ins philosophieren!
Wenn ich mir vorstelle, was sich in den zwanzig Jahren getan hat, was aus meinen ersten 486 25MHz Computer geworden ist.
Da war man noch stolz auf eine 200 MB Festplatte
MfG Andreas
Aber lassen wir das, sonst kommt man ja noch ins philosophieren!
Wenn ich mir vorstelle, was sich in den zwanzig Jahren getan hat, was aus meinen ersten 486 25MHz Computer geworden ist.
Da war man noch stolz auf eine 200 MB Festplatte
MfG Andreas