Abfrage serielle Schnittstelle

Alle Fragen um die Programmierung, die sich sonst nicht kategorisieren lassen. Von Makro bis Codeblock, von IF bis ENDIF

Moderator: Moderatoren

Antworten
Benutzeravatar
Rudolf
Programmier-Gott
Programmier-Gott
Beiträge: 1418
Registriert: Mo, 02. Jan 2006 23:03
Wohnort: Salzburg/Österreich
Kontaktdaten:

Abfrage serielle Schnittstelle

Beitrag von Rudolf »

Hallo,
suche eine Lösung für das Einlesen von Daten über die serielle Schnittstelle und sofortige Auslösung eines Events o.ä. Ich muss für ein Bonierungssystem den Kellnerschlüssel seriell abfragen bzw. auf einen seriellen Kartenleser reagieren. Die Reaktion vom System sollte sehr schnell sein, daher müsste ich die Schnittstelle in einem anderen Thread ständig abfragen. Finde die Lösung aber nicht sehr elegant.
Ideal wäre ein AcitveX Control, welches eine Ereignis auslöst.
Hat jemand schon Erfahrung damit ?
Grüsse
Rudolf
Benutzeravatar
andreas
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 1902
Registriert: Mi, 28. Sep 2005 10:53
Wohnort: Osnabrück
Hat sich bedankt: 4 Mal
Kontaktdaten:

Beitrag von andreas »

Hallo Rudolf,

wir benutzen auch Serielle Schnittstellen mit XBase-Tools. Über Zugriff mit ActiveX kann ich nur sagen dass es irgendwelche Standartschnittstelle von Microsoft gibt. Versuchs mit Microsoft Communication Control, den du direkt mit XppFd einfügen kannst.

Ich glaube aber, dass ohne ständiges Abfragen nichts laufen wird.
Gruß,

Andreas
VIP der XUG Osnabrück
Benutzeravatar
brandelh
Foren-Moderator
Foren-Moderator
Beiträge: 15689
Registriert: Mo, 23. Jan 2006 20:54
Wohnort: Germersheim
Hat sich bedankt: 65 Mal
Danksagung erhalten: 33 Mal
Kontaktdaten:

Beitrag von brandelh »

Hallo Rudolf,

in den XbToolsIII gibt es Funktionen zur Überwachung der seriellen Schnittstelle. Diese sind Eventgesteuert. Ein Bekannter hat damit den seriellen Druckerausgang eines Gerätes angezapft und die Daten importiert (schon unter clipper), war recht aufwändig, insbesondere mußte er mit den Timeouts experimentieren. Nun funktioniert es aber gut.

wenn du die Tools (in Subscription ...) nicht hast, schau auf der Alaska Seite nach ComSilver oder so ähnlich, eine Toolbox für die serielle Schnittstelle ...
Gruß
Hubert
Benutzeravatar
Rudolf
Programmier-Gott
Programmier-Gott
Beiträge: 1418
Registriert: Mo, 02. Jan 2006 23:03
Wohnort: Salzburg/Österreich
Kontaktdaten:

Beitrag von Rudolf »

Hallo,
danke an alle, habe die Tools und werde es mit einem eigenen Thread probieren der auf eine COM Event wartet.
Grüsse
Rudolf
Gerd König
Rekursionen-Architekt
Rekursionen-Architekt
Beiträge: 193
Registriert: Fr, 09. Jun 2006 7:52
Wohnort: Nähe Sömmerda

Beitrag von Gerd König »

Hallo Rudolf,

ich würde schon die Schnittstellenabfrage in einem eigenen Thread ausführen und in diesem auch die empfangenen Daten in einen Empfangsbuffer schreiben. Der Buffer könnte z.B. durch den Main-Thread überwacht werden, eventuell kann auch ein User-Event an das Hauptfenster gesendet werden, wenn Daten emfangen wurden.

Grüße
Gerd
Benutzeravatar
Rudolf
Programmier-Gott
Programmier-Gott
Beiträge: 1418
Registriert: Mo, 02. Jan 2006 23:03
Wohnort: Salzburg/Österreich
Kontaktdaten:

Beitrag von Rudolf »

Hallo Gerd,
habe an diese Lösung gedacht, nur das mit dem User Event habe ich nocht nicht so richtig drauf. Muss mal nach einem Beispiel im Forum suche, dürfte aber nicht so schwierig sein. Habe die Funktion COM_EVENT() in den Tools gefunden, die könnte ich verwenden.
Grüsse
Rudolf
Gerd König
Rekursionen-Architekt
Rekursionen-Architekt
Beiträge: 193
Registriert: Fr, 09. Jun 2006 7:52
Wohnort: Nähe Sömmerda

Beitrag von Gerd König »

Hallo Rudolf,

zum User-Event:

Zuerst wäre dieses Ereignis zu definieren, am besten in einer ch-Datei

Code: Alles auswählen

#include "appevent.ch"
#define MY_EVENT  xbeP_User+1
Im COM-Thread ist dann

Code: Alles auswählen

PostAppEvent(MY_EVENT, mp1, mp2, SetAppWindow())
aufzurufen.


Im Main-Thread würde ich dann innerhalb des Eventloops die Auswertung ausführen:

Code: Alles auswählen

DO WHILE .T.
   nEvent := AppEvent( @mp1, @mp2, @oXbp, 50) //0,5s Timeout
   IF (nEvent=MY_EVENT)
      HandleMyEvent() //zur Auswertung
      LOOP
   ENDIF
   oXbp:handleEvent( nEvent, mp1, mp2 )
ENDDO

Gruß
Gerd
Benutzeravatar
Koverhage
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 2470
Registriert: Fr, 23. Dez 2005 8:00
Wohnort: Aalen
Hat sich bedankt: 102 Mal
Danksagung erhalten: 3 Mal
Kontaktdaten:

Beitrag von Koverhage »

Hubert,
die Tools sind bei jeder subscription dabei.
Benutzeravatar
Rudolf
Programmier-Gott
Programmier-Gott
Beiträge: 1418
Registriert: Mo, 02. Jan 2006 23:03
Wohnort: Salzburg/Österreich
Kontaktdaten:

Beitrag von Rudolf »

Hallo Gerd,
danke für den Tip, habe diese Classe erstellt, die aber leider nicht funktioniert. Bin kein OOP Profi und kann den Fehler einfach nicht finden, ist sicher nur eine Kleinigkeit. Beim Starten bekomme ich immer folgende Meldung:

oError:args :
-> VALTYPE: O CLASS: ComThread
oError:canDefault : N
oError:canRetry : N
oError:canSubstitute: J
oError:cargo : NIL
oError:description : Access to method not allowed in this context
oError:filename :
oError:genCode : 25
oError:operation : startcom
oError:osCode : 0
oError:severity : 2
oError:subCode : 2223
oError:subSystem : BASE
oError:thread : 1
oError:tries : 0
------------------------------------------------------------------------------
CALLSTACK:
------------------------------------------------------------------------------
Called from START_THREAD(7437)
Called from (B)PROG_START(648)
Called from DC_GETLIST:READGUI(3284)
Called from DC_READGUI(223)
Called from PROG_START(648)
Called from PROGMAIN(206)
Called from MAIN(49)

DBE Component Data :DBFDBE
DBE Component Order:CDXDBE

No DBF file open


hier meine Klasse:

function start_thread()
******************************************************************
local o:=ComThread():new()
sleep(5)
o:start()
o:startcom()
return o


CLASS ComThread FROM THREAD
******************************************************************
method atend
method startcom
method stopcom

INLINE METHOD init
::Thread:init()
::nComNr := 1
::cKey := ""
::terminated := .f.
RETURN self

INLINE METHOD terminate

RETURN ( ::terminated := .T. )


EXPORTED:
var cKey
var nComNr
PROTECTED:
VAR terminated

ENDCLASS


METHOD ComThread:startcom()
******************************************************************
local nEvent,cIN
::lAktiv := .f.
if ::nComNr > 0
if COM_OPEN(::nComNr)
com_init(::nComNr,9600,"N",8,1)
com_rts(::nComNr,.t.)
com_dtr(::nComNr,.t.)
::lAktiv := .t.
endif
endif
if ::lAktiv
do while ::lAktiv
if ::terminated
::terminated := .f.
::quit()
endif
nEvent := com_event(::nComNr,COM_EVENT_CHAR)
if nEvent = COM_EVENT_CHAR
cIn := com_read(::nComNr,100)
if !empty(cIn) .and. "OUT" $ cIn
if len(cIn) > 10
::cKey := cIn
PostAppEvent(COM_KEY_EVENT, mp1, mp2, SetAppWindow())
else
::cKey := "OUT"
endif
endif
endif
enddo
endif
return self


METHOD ComThread:atEnd()
******************************************************************
if ::lAktiv
com_close(::nComNr)
endif
::lAktiv := .f.
return self


METHOD ComThread:stopcom()
******************************************************************
::lAktiv := .f.
return self


Grüsse
Rudolf
Gerd König
Rekursionen-Architekt
Rekursionen-Architekt
Beiträge: 193
Registriert: Fr, 09. Jun 2006 7:52
Wohnort: Nähe Sömmerda

Beitrag von Gerd König »

Hallo Rudolf,

deklariere deine Methoden als EXPORTED. Dann sollte es funktionieren...

Grüße
Gerd
Benutzeravatar
Rudolf
Programmier-Gott
Programmier-Gott
Beiträge: 1418
Registriert: Mo, 02. Jan 2006 23:03
Wohnort: Salzburg/Österreich
Kontaktdaten:

Beitrag von Rudolf »

Hallo Gerd,
vielen Dank, jetzt funktioniert es
Grüsse
Rudolf
Antworten