Off Topic

PHP und die serielle Schnittstelle

6 Jan , 2009  

Aktuelle PCs werden schon fast gar nicht mehr mit einer, oder gar mehreren seriellen Schnittstellen ausgeliefert. Trotzdem gibt es aber noch viele Anwendungen und Geräte die mit einer seriellen Schnittstelle ausgestattet sind und damit ausgezeichnet am PC funktionieren.

Tausendfach bewährt sind dabei z.B. Bondrucker in Kassensystemen. Vorteil dieser Bondrucker ist Ihre enorme Geschwindigkeit, mit der sie leise und unauffällig Kassenbons drucken. Die Datenmenge ist für so einen Bon gering, da nur die reinen Druck-Zeichen als ASCII Code übertragen werden und keine Grafik wie bei anderen Windows Druckern.

Meist läuft dann auf dem Kassen-PC eine Windows Software die, problemlos einen Zugriff auf die Hardware-Schnittstellen des PCs hat. Möchte man aber z.B. so eine Kassensoftware als vorteilhafte ASP- oder Webanwendung mit PHP programmieren, hat man das Problem, dass die vom Server erzeugte Webseite im Browser meist keinen Zugriff auf die Hardware des Client-PCs hat. Aus Sicherheitsgründen ist das nachvollziehbar.

Möglichkeiten zum ansprechen der seriellen Schnittstelle auf dem Client PC wären z.B. ein signiertes Java-Applet, oder ein ActiveX Control, welches von dem Browser mit geladen und ausgeführt wird. Nach dem Bestätigen von etlichen Sicherheitswarnungen würde der Benutzer dann auch sicherlich etwas auf seiner seriellen Schnittstelle ausgeben können. Allerdings sind diese beiden Lösungen nicht einfach zu programmieren.

Sehr viel einfacher und eleganter ist da schon die Nutzung der auf jedem Windows Rechner vorhanden Standardanwendung cmd.exe. Der Windows Kommandozeileninterpreter cmd.exe (kurz CLI oder auch Windows-Befehlsprozessor) ermöglicht das Ausführen von Skripten und ist ein mächtiges Tool.

Um aus PHP die serielle Schnittstelle anzusprechen, erzeugt man sich einfach ein File mit den ASCII Daten, die über die Schnittstelle gesendet werden sollen. Ein Beispiel PHP Code für das Erzeugen der Daten für einen Kassenbon inklusive der Codes für Vorschub, Papierschneider und öffnen der Kassenlade gibt es hier:

Mit der PHP Funktion chr(); werden dabei ASCII Steuerzeichen wie ESC erzeugt, die normal nur schwer mit einer Tastatur in ein Textfile eingegeben werden können. Die ESC Sequenzen sind nötig um den hier verwendeten Bondrucker Epson TM88 nach dem ESCPOS Standard an zu steuern. Damit werden die Schriftgröße, Zeilenvorschub usw. eingestellt.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
<?php
header("Content-type: application/vnd.ms-excel"); 
header("Content-disposition: attachment; filename=bon_to_printer.prser");
header("Pragma: no-cache");
header("Expires: 0");
  
echo chr(27) . "@";  //Initializes the printer (ESC @)
echo chr(27) . "a" . chr(1); 
//Specifies a centered printing position (ESC a)
echo chr(27) . "!" . chr(0);  //Specifies font A (ESC !)
echo "January 14, 2008 15:00";
echo chr(27) . "d" . chr(3);
//Prints and 3 line feeding (ESC d)
echo chr(27) . "a" . chr(0);  
//Selects the left print position (ESC a)
echo chr(27) . "!" . chr(1);  //Selects font B
echo "TM-U210B $20.00" . chr(10) ;
echo "TM-U210D $21.00" . chr(10) ;
echo "PS-170 $17.00" . chr(10) ;
echo chr(10);         //Line feeding (LF)
echo chr(27) . "!" . chr(17);
//Selects double-height mode
echo "TOTAL $58.00" . chr(10);
echo chr(27) . "!" . chr(0);
//Cancels double-height mode
echo "------------------------------" . chr(10) ;
echo "PAID $60.00" . chr(10) ;
echo "CHANGE $ 2.00" . chr(10) ;
echo chr(29) . "V" . chr(66) . chr(0); 
//Feeds paper &amp; cut ’Drawer Kick (ESC p)
echo chr(27) .  chr(112) . chr(0) . chr(60) . chr(120); 
?>

Der eigentliche Trick dabei ist nun, eine Datei mit der neuen Dateiendung .prser zu erzeugen. Diese Dateiendung kann man dann unter Windows einer Anwendung zugeordnet werden. Und diese „Anwendung“ ist folgender kleiner Zweizeiler: print.bat

1
2
MODE COM1:38400,N,8,1
copy %1 COM1

Das Batchfile print.bat stellt in der ersten Zeile die Werte für die COM Schnittstelle ein. In der zweiten Zeile werden alle an das Batchfile übergebenen Daten auf die angegebene COM Schnittstelle gesendet. Welches die richtige COM Schnittstelle ist, kann man in den Systemeinstellungen im Geräte-Manager erkunden. Speziell bei der Verwendung von USB-COM Adaptern sind die virtuellen COM Schnittstellen meist recht hohe und ggf. auch zufällige Nummern.

Möchte man, dass nach dem Erzeugen der ASCII Datei der Druck sofort ohne Meldung und Bestätigen beginnt, muss man beim Registrieren der Anwendung im Explorer unter Extras -> Ordneroptionen -> Reiter Dateitypen -> Erweitert den Haken bei „Öffnen nach dem Download bestätigen“ entfernen.

Screenshot: Einstellen der Dateiverknüpfung

Screenshot Einstellen der Dateiverknüpfung

Nachteil dieser Lösung ist, dass die print.bat natürlich auf dem Client Rechner vorhanden sein muss. Bei einem Rechner, der als Kasse mit einem Bondrucker ausgestattet ist, ist das aber kein Problem. Dafür ist die Programmierung und Verwendung ausgesprochen einfach und geradlinig.

, , , , , ,


19 Responses

  1. […] Tutorial … so es hat etwas gedauert, aber ich habe das Thema PHP und serielle Schnittstelle noch einmal in einem kleinen Tutorial in meinem Blog zusammen gefasst. Die php Testdatei erzeugt […]

  2. Axel sagt:

    hi, super sache!
    wollte es gerade testet
    allerdings habe ich keinen DateiTyp „Serial POS Drucker“
    kommt der erst mit der Druckerinstallation oder kann ich den manuell anlegen?

    Grüße
    Axel

  3. fsc sagt:

    …Nein den Datei Typ muss man sich selbst neu anlegen.

    Z.B. im Explorer Extras-> Orderoptionen -> Tab-Dateitypen -> Button NEU.
    Dann die Dateiendung angeben und unter erweitert zur eigenen .bat Datei browsen und diese hier verknüpfen. So gings bei mir.

    Alternativ kann man auch die Druckerdatei mit der eigenen Dateiendung vom PHP Server erzeugen lassen und dann im Dialog bei Öffnen den Dialog Öffnen mit durchlaufen.

  4. Axel sagt:

    juhuu, bei mir geht´s jetzt

    musste mich noch voll damit rumärgern, dass firefox mir die Datei einfach nicht öffnen wollte!

    Es ging dann mit folgender Änderung
    Zeile:
    header(„Content-disposition: attachment; filename=bon_to_printer.prser“);
    –> Ersetze „attachment“ durch „inline“! Dann geht´s

  5. CTO sagt:

    Leider geht es auch mit „inline“ nicht.

    Das Herunterladen des .bonpos-Files (so habe ich es genannt) funktioniert, aber das Aufrufen der print.bat schafft er nicht. 🙁

  6. Marco sagt:

    Ich habe auch einen Bon-Drucker,jedoch mit USB Anschluss. Wie kann ich diesen im Batch-File ansteuern?

    Dankschön!

  7. fsc sagt:

    Bei den USB Versionen von Bon Druckern muss man unterscheiden, ob es sich um echte USB Drucker handelt oder um serielle Drucker, die nur per USB-seriell Wandler aufgebohrt wurden.

    Bei der zweiten Variante mit dem USB-seriell Wandler gibt es einmal eine externe Lösung mit externen Adapterkabeln oder mit internen Wandlerschaltkreisen wie z.B. einem FTDI FT232.

    Unterscheiden kann man dies, in dem man auf dem PC unter Systemsteuerung -> System -> Hardware -> Geräte-Manager die Geräte sucht.

    Sofern der Drucker unter „Anschlüsse(COM und LPT)“ aufgeführt wird, z.B. als Eintrag „USB Seriel Port (COMx)“ hat man den passenden COM Port gefunden und muss in dem Batch File nur den passenden COM Port einstellen.

    Ist es nicht klar, welcher COM Port hier dem USB Anschluss zugeordnet ist, kann man auch bei geöffnetem Geräte Manager einfach mal den USB Drucker abziehen und beobachten welcher Port verschwindet und wieder beim einstecken erscheint.

    Wird der Drucker aber nur mit dem USB Icon als separates Device oder unter dem Eintrag USB-Controller gelistet, fällt eine einfache Ansprache des Druckers per Batch File leider aus.

    In dem Fall wird für die Drucker meistens eine DLL oder ein Treiber bereit gestellt, mit dem man dann auf den Drucker zugreifen kann. Möglich wäre es dann eine ActiveX Komponente zu schreiben, die auch direkt über die Webseite gestartet werden kann. Alternativ kann auch eine eigens entwickelte Konsolenanwendung programmiert werden, welche die Eingabedaten verarbeitet und über den Druckertreiber an den Drucker sendet. An Stelle des Batchfiles müsste dann diese Konsolenapplikation mit dem Bon-File verknüpft werden.

    Ich denke aber, dass zur Zeit die meisten Drucker einfach nur mit USB-seriell Wandlern auf den neuen Standart gebracht wurden, da die meisten Kassenanwendungen immer noch mit den einfachen und robusten seriellen Protokollen arbeiten.

    Zwei Anmerkungen noch:
    1. In meinem Beispiel des Batch Files habe ich als Baudrate 38400 Baud programmiert. Diese Baudrate muss natürlich mit den Einstellungen am Drucker übereinstimmen!

    Bei mir habe ich die Standard-Einstellung von 9600 Baud geändert auf 38400 Baud, um eine schnellere Kommunikation zu erreichen. Bei den wenigen übertragenen Daten für einen Bon fällt die Geschwindigkeit aber kaum ins Gewicht und bei langen und schlechten Kabeln kann eine höhere Übertragungsgeschwindigkeit durchaus auch negativ sein.

    Die Baudrate wird beim TM 88 mit DIP Switches eingestellt, die auf dem Geräteboden unter einer Abdeckplatte versteckt sind.

    2. Die Bon-Drucker verwenden ASCII Zeichensätze. Bei den ASCII Zeichensätzen sind nur die ersten 128 Zeichen einigermaßen genormt bzw. gleich. Sonderzeichen befinden sich meistens im Bereich von 128 – 256. Will man also deutsche Umlaute und Sonderzeichen drucken, muss man die erst mal im Druckerzeichensatz suchen und dann bei der Ausgabe diese Zeichen vom „PHP“-Unicode in den ASCII Zeichensatz umcodieren.

    Man kann sich dazu einfach mal alle Zeichen im Bereich von ASCII(30) bis ASCII(256) drucken lassen. Dann kennt man die Codes der Sonderzeichen und kann damit seinen Ausgabetext z.B. mit str_replace() umcodieren.

  8. Kai sagt:

    Hi, genau danach habe ich gesucht.

    Habe auch alles nach Anweisung ausgeführt und eingestellt, jedoch fragt der IE8 immer noch „Öffnen“ oder „Speichern“.
    Wenn ich probeweise „attachment“ durch „inline“ ersetze öffnet er zwar automatisch, aber Excel. Hmm?!?

    Für Hilfestellung wär ich sehr Dankbar.

  9. fsc sagt:

    @Kai,

    Hm, mit dem IE8 habe ich es noch nicht ausprobiert, einfach weil ich nicht so gerne Beta Versionen auf meinem Rechner mag. Vielleicht probiere ich es demnächst mal in einer VM aus.

    Ob attatchment oder inline als Attribut ist eigentlich egal, solange man bei Windows bei „Dateityp Bearbeiten“ den Haken entfernt bei “Öffnen nach dem Download bestätigen”.

    Der Content Typ spielt eigentlich keine Rolle. Teilweise erkennt Windows darüber die Applikation, die gestartet werden soll. Aber dann muss auch die Dateiendung stimmen. Da wir die aber hier explizit auf dem Rechner festlegen ist es eigentlich egal.

    Ich hatte den header() Codeschnipsel immer für CSV Exporte verwendet. Wenn dort die Dateiendung .csv lautet, und der Content-Type so codiert wird öffnet der CSV Export automatisch in Excel… und das ist dann bequem 😉

  10. […] einer Weile hatte ich meine Erfahrungen mit der Ansteuerung eines Bondruckers EPSON TM 88 mit PHP aus einer Webanwendung beschrieben.  Rund um den Artikel ist doch eine ordentliche Diskussion […]

  11. sn2k sagt:

    Ich habe eine Frage ich haben von Windows auf Linux gewechselt nun generiere ich ja eine .pser datei, wie kann ich das shell script

    MODE COM1:38400,N,8,1
    copy %1 COM1

    umbauen auf MacOS Shell Script??
    Gerät ist /dev/tty-usb….

    Danke

  12. fsc sagt:

    @sn2k

    Sorry, aber bei MacOS muss ich leider passen.

  13. dh sagt:

    Die grundsätzliche Idee finde ich sehr schlau. Leider habe ich es nicht geschafft das Ganze unter Windows 7 zum Rennen zu bekommen.
    Zum einen konnte ich keine .bat Datei in einem Standard-Programmverzeichnis speichern und dann eine Dateiendung damit verknüpfen. Das scheint Win7 zu verhindern.
    Zum anderen funktionierte der DOS-Befehle „copy testdatei.txt com3“ nicht. Das BS sagt mir „ugriff verweigert“, obwohl der Drucker auf com3 registriert ist. Hat jemand einen Tipp für mich?
    Vielen Dank und Grüße
    Dirk

  14. fsc sagt:

    Hallo dh,

    unter win7 geht es auch. Die print.bat z.B. ins Verzeichnis c:/programme legen. Sofern man nicht als Administrator eingeloggt ist, muss man mit der rechten Maustaste die Eigenschaften der print.bat aufrufen und dort im Tab Kompatibilität den Haken bei „als Administrator ausführen“ setzen.

    Die .prser Datei kann man auch unter WIN7 mit der print.bat verknüpfen. Z.B. auch unter Eigenschaften. Eigentlich kein Thema.

  15. […] als 3. Parameter) erstellen und den Download damit öffnen. Weitere Informationen dazu sind hier zu […]

  16. Matthew sagt:

    Aufgrund eines aktuellen Projektes habe ich mal dem Thema der Benutzerdefinierten Zeichen gewidmet und dafür gleich einen Zeichengenerator in PHP geschrieben: http://www.mfdweb.de/technik/zeichengenerator/

    Damit kann man sich seine „Strickmuster“ individuell zusammenklicken und erhält als Ergebnis den benötigten Steuerbefehl. Natürlich kann auch gleich die „Bon to Printer“ -Datei für einen ersten Test erzeugt werden und besonders gelungene Zeichen lassen sich im Archiv veröffentlichen.

    Ich hoffe es funktioniert auch auf euren Druckern und ich wünsche viel Spaß beim Experimentieren… 😉

    Gruß Matthew

    P.S. Über euer Feedback würde ich mich natürlich sehr freuen!

  17. Adam Nielsen sagt:

    Ich habe einen Drucker, der leider unter USB-Controller gelistet ist.

    Wie kann ich diesen jetzt ansprechen? Du hast in einem alten Beitrag geschrieben, mithilfe von ActiveX ? Kannst du das erläutern?

    Danke! Lg, Adam

  18. fsc sagt:

    Hallo Adam,

    wenn der Drucker in der Systemstuerung -> Hardware unter USB angezeigt wird könnte es sein, dass

    A: es ein serieller Drucker ist, der mit einem USB/Seriell Wandler z.B. von FTDI auf USB kompatibilität gepimpt wurde. Dann gibt es einen eintrag unter USB und einen weiteren als virtuellen COM Port. Den Virtuellen COM Port kann man dann ganz normal wie oben beschrieben ansprechen.

    B: wenn es sich um einen echten Drucker handelt, muss man dessen Druckertreiber intallieren. Wenn man dann direkt aus der Webanwendung – schnell und ohne Druckerdialog – drucken möchte, könnte man ein ActiveX Plugin für den Webbraowser schreiben. Das Plugin bekommt dann direkt die Daten von der Webseite und schickt sie an den Drucker. Ganz einfach – für jemanden der so was kann 😉 Ich kann es nicht…

  19. Ati sagt:

    Hallo,

    Danke für dieses tolle Tutorial. Ich hab die BAT-Datei und PHP-Datei etwas umgeschrieben, sodass ein Download der Datei unnötig geworden ist. In der PHP-Datei habe ich lediglich die Header-Sektion entfernt, die BAT Datei wiefolgt umgeschrieben:

    MODE COM2:38400,N,8,1
    php.exe print_bon_test_uml.php > COM2

    …so druckts direkt aus der Datei. Auch gibt es für jene, welche ein USB-Gerät zur verfügung haben eine Lösung. auf der Epson-Seite gibt es ein „Virtual Port Driver“ welche den seriellen Port Emuliert.

    Ich bin lediglich beim NV-Logo stecken geblieben. Welches Zeichen ist das richtige dazu?

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.