29

質問があります。私が現在取り組んでいる学校の Java プロジェクトでは、ラップトップに接続する外部入力として USB バーコード スキャナーが必要です。USBスキャナーは学生にはかなり高価なので、実際には購入していません。そのため、このスキャナーが私のプログラムで動作するという証拠を収集する必要があります。

スキャナはバーコード (おそらくオンラインで印刷されたもの) から読み取り、それを変数に格納できますか? もしそうなら、スキャナーを押したときのアクション イベントが、キーボードのキーを押すのとまったく同じように読み取られるというのは本当ですか? もしそうなら、コード行はどのようになりますか?

また、バーコード スキャナーを使用した経験を投稿したり、どのスキャナーを購入するかなどのアドバイスを提供していただければ、非常に役立ちます。乾杯!

4

4 に答える 4

34

最近、Java と対話するためのスキャナー システムを実装する必要がありました。

Honeywell Voyager MS9540 USB バーコード スキャナーを使用しました。

デフォルトでは、スキャナはデータをキーボード入力として直接送信します - ドライバは必要ありません。

しかし、キーボードフックを使用するのではなく、このモデルを Java と直接対話させるのは非常に簡単でした(前述のように、バーコードを Java の変数として使用するため)。

このモデルにはシリアル ポートをエミュレートする設定があり、javax.comm パッケージを使用してスキャンしたデータを読み取ることができます。私にとっては、これはバーコード データを取得するためのキーボード フックよりもはるかに優れていました。これは、プログラムがスキャンを解釈できるようになる前にフォーカスを必要としないためです (グローバル キーボード フックを作成したくありません)。

私の Java プログラムは、指定されたシリアル ポートからすべての入力を読み取り、バーコードをデータベースに書き込みます。また、認識されていないバーコード スキャンをキーボードに渡すようにプログラムをセットアップしました (アプリが作成しなかったバーコード - バーコードに個別の署名を使用しました)。キーボードからバーコードを読み取ります。

おそらく、集中的な JNI コーディングを行うことで、(このモデルに搭載されているシリアル ポート エミュレーションなしで) USB スキャナーから直接データを読み取ることができますが、私はネイティブ コードを作成する時間を取る準備ができていませんでした。

この特定のモデルをシリアル ポート エミュレーション用に構成するには、構成したいスキャナーでこのドキュメントの特定のバーコードをスキャンするだけです。「Serial Emulation Mode」というタイトルのバーコードです。

このスキャナには、シリアル ポート エミュレーション用のドライバが必要です。ここで実装手順と必要なドライバーを見つけました(「ソフトウェア」タブの下)。「Honeywell Scanning and Mobility (HSM) USB Serial Driver」というタイトルのパッケージをダウンロードします。「HSM USB Serial Driver Getting Started Guide」というタイトルの PDF に手順が記載されていました。

javax.comm API に慣れていない場合。Rick Proctor によるこの例のイントロを読んでください。jar を取得する場所とファイルを配置する場所が示されています (javax.comm は、ほとんどの Java パッケージに標準で付属していません)。

シリアル ポート エミュレーションを備えた他のスキャナ モデルがあることは確かです (私は Honeywell で働いていません)。

これは、私のバーコード リーダー クラスのやや簡略化されたバージョンです。

package scanhandler;


import java.awt.AWTException;
import java.awt.Robot;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.util.Enumeration;
import java.util.Properties;
import java.util.TooManyListenersException;
import javax.comm.CommPortIdentifier;
import javax.comm.PortInUseException;
import javax.comm.SerialPort;
import javax.comm.SerialPortEvent;
import javax.comm.SerialPortEventListener;
import javax.comm.UnsupportedCommOperationException;

public class ScanHandler implements Runnable, SerialPortEventListener {

    private static CommPortIdentifier   myCommPortIdentifier;
    private static Enumeration          portList;
    private static String               TimeStamp;
    private static String               driverClass;
    private static String               connectionString;
    private static String               comPort;    

    private Connection                  myConnection;
    private InputStream                 myInputStream;
    private Robot                       myRobot;
    private SerialPort                  mySerialPort;
    private Thread                      myThread;


    public ScanHandler() {

        // open serial port
        try {
            TimeStamp = new java.util.Date().toString();
            mySerialPort = (SerialPort) myCommPortIdentifier.open("ComControl", 2000);
            //System.out.println(TimeStamp + ": " + myCommPortIdentifier.getName() + " opened for scanner input");
        } catch (PortInUseException e) {
            e.printStackTrace();
        }

        // get serial input stream
        try {
            myInputStream = mySerialPort.getInputStream();
        } catch (IOException e) {
            e.printStackTrace();
        }

        // add an event listener on the port
        try {
            mySerialPort.addEventListener(this);
        } catch (TooManyListenersException e) {
            e.printStackTrace();
        }
        mySerialPort.notifyOnDataAvailable(true);

        // set up the serial port properties
        try {
            mySerialPort.setSerialPortParams(9600,
                SerialPort.DATABITS_8,
                SerialPort.STOPBITS_1,
                SerialPort.PARITY_NONE);
            mySerialPort.setDTR(false);
            mySerialPort.setRTS(false);

        } catch (UnsupportedCommOperationException e) {
            e.printStackTrace();
        }

        // make a robot to pass keyboard data
        try {
            myRobot = new Robot();
        } catch (AWTException e) {
            e.printStackTrace();
        }

        // create the thread
        myThread = new Thread(this);
        myThread.start();
    }

    public void run() {
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {}
    }

    // on scan
    public void serialEvent(SerialPortEvent event) {

        if (event.getEventType() == SerialPortEvent.DATA_AVAILABLE) {

            StringBuilder myStringBuilder = new StringBuilder();
            int c;
            try {

                // append the scanned data onto a string builder
                while ((c = myInputStream.read()) != 10){
                   if (c != 13)  myStringBuilder.append((char) c);
                }               

                // send to keyboard buffer if it the barcode doesn't start with '5'
                if (myStringBuilder.charAt(0) != '5') {

                    for (int i = 0; i < myStringBuilder.length(); i++) {
                        myRobot.keyPress((int) myStringBuilder.charAt(i));
                        myRobot.keyRelease((int) myStringBuilder.charAt(i));
                    }

                // here's the scanned barcode as a variable!
                } else {
                    TimeStamp = new java.util.Date().toString();
                    System.out.println(TimeStamp + ": scanned input received:" + myStringBuilder.toString());                    
                }

                // close the input stream
                myInputStream.close();

            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    public static void main(String[] args) {

        // read ScanHandler properties
        Properties myProperties = new Properties();
        try {
            myProperties.load(new FileInputStream("config.properties"));
            comPort             = myProperties.getProperty("ScanHandler.comPort");
        } catch (IOException e) {
            e.printStackTrace();
        }              

        try {

            // get our pre-defined COM port
            myCommPortIdentifier = CommPortIdentifier.getPortIdentifier(comPort);
            ScanHandler reader = new ScanHandler();

        } catch (Exception e) {
            TimeStamp = new java.util.Date().toString();
            System.out.println(TimeStamp + ": " + comPort + " " + myCommPortIdentifier);
            System.out.println(TimeStamp + ": msg1 - " + e);
        }
    };    
}
于 2011-12-23T22:42:05.767 に答える
11

私が使用したバーコード スキャナーは、キーボード デバイスのように機能しました (オペレーティング システムでは HID キーボード USB デバイスとして表示されました)。バーコードがスキャンされると、入力されたかのようにコードが送信されました。それと対話するために特別な API は必要ありませんでした。

于 2011-11-16T04:51:15.320 に答える
8

かなり古いスレッドであることは知っていますが、検索でそこにたどり着くことができます。

これは、Geronimo の回答への追加として扱うことができます。

Linux OS の場合、USB シリアル ポートがネイティブにサポートされているため、シリアル エミュレーション モードでバーコード スキャナー用のドライバーをインストールする必要はありません。いくつかのタイプの Honeywell スキャナーを使用していますが、それらはすべて箱から出してすぐに使用できます。シリアル エミュレーションのスキャナーは、システムで /dev/ttyACM0、/dev/ttyACM1 などとして表示されます。

最近、シリアル ポートとインターフェイスするための Java ライブラリとして、javax.comm から jssc に切り替えました。よく覚えていると思いますが、Windows 7 64 ビット システムでは、javax.comm ライブラリはシリアル ポートから読み書きできず、jssc には非常によく似た API があります。

于 2015-01-21T06:51:57.440 に答える
0

これは古い質問だと思いますが、バーコード スキャナーの入力をシミュレートするための追加のソリューションを追加すると考えました。このソリューションは、スキャナ入力をキーボード データとしてシミュレートする場合にのみ機能します。

スキャナーはキーボード入力のみを使用することが多いため、 AutoHotkeyスクリプトを使用してこれをシミュレートできます。以下はスクリプトの例です。

#NoEnv  ; Recommended for performance and compatibility with future AutoHotkey releases.
; #Warn  ; Enable warnings to assist with detecting common errors.
SendMode Input  ; Recommended for new scripts due to its superior speed and reliability.
SetWorkingDir %A_ScriptDir%  ; Ensures a consistent starting directory.

; Barcode 1
; Hotkey = ctrl + alt + 1
^!1::
    SendInput [BC200015]
Return

; Barcode 2
; Hotkey = ctrl + alt + 2
^!2::
    SendInput [BC300013]
Return

[BC300013]and[BC200015]を、予想されるスキャナー入力に 置き換えるだけです。

于 2015-08-19T20:46:38.753 に答える