Bezdepbonusu7Программирование: статьи и ответы

Вопрос

Реализация сканера штрих-кода на Java

Автор вопроса: user976123Ответов: 4

Господа, у меня вопрос. Школьный Java-проект, над которым я сейчас работаю, требует, чтобы у меня был USB-сканер штрих-кода в качестве внешнего входа для подключения к моему ноутбуку. На самом деле я не купил USB-сканер, так как он довольно дорогой для студента. Так что я должен собрать доказательства того, что этот Сканер будет работать с моей программой.

Сможет ли сканер считывать штрих-код (предположительно, распечатанный онлайн) и сохранять его в переменной? Если да, то правда ли, что событие действия для нажатия сканера будет считываться точно так же, как нажатие клавиши на клавиатуре? Если да, то как будет выглядеть строка кода?

Кроме того, если бы вы могли опубликовать свой опыт работы со сканерами штрих-кода или дать какой-либо совет, например, какой сканер купить, это очень помогло бы. Ваше здоровье!

  • Если ваш курсор находится в текстовом поле или поле ввода, сканер просто "запишет" туда код. В сканере нет ничего особенного. Вы не получите событие. Однако, если у вас есть веб-страница, вы можете попробовать что-то вроде события OnChange JS. Nishant 16.11.2011

javaeventsactionbarcode-scannerscanning

Ответы

Ответ 1 · рейтинг 32 · egerardus

Недавно мне пришлось внедрить систему сканирования для взаимодействия с java.

Я использовал USB-сканер штрих-кода Honeywell Voyager MS9540.

По умолчанию сканер отправляет данные прямо в виде ввода с клавиатуры - драйвер не требуется.

Но было очень легко заставить эту модель взаимодействовать напрямую с java, а не использовать клавиатурный хук (чтобы использовать штрих-коды в качестве переменных в java, как вы упомянули).

Эта модель имеет настройку для эмуляции последовательного порта, после чего вы можете прочитать отсканированные данные с помощью пакета javax.comm. Для меня это было намного лучше, чем клавиатурный хук для получения данных штрих-кода, потому что программе не нужен фокус, прежде чем она сможет интерпретировать сканирование (я бы не хотел создавать глобальный клавиатурный хук) .

Моя программа Java считывает все входные данные с указанного последовательного порта и записывает штрих-код в базу данных. Я также настроил программу для передачи любых нераспознанных сканированных штрих-кодов на клавиатуру (любой штрих-код, который не был создан моим приложением - я использовал отдельную подпись для своих штрих-кодов), чтобы он работал как обычный сканер штрих-кода для любых других приложений, которые могут считывать штрих-коды с клавиатуры.

Вероятно, вы могли бы считывать данные напрямую с любого USB-сканера (без эмуляции последовательного порта, которая есть в этой модели), выполняя интенсивное кодирование JNI, но я не был готов тратить время на разработку собственного кода.

Чтобы настроить эту конкретную модель для эмуляции последовательного порта, все, что вам нужно сделать, это отсканировать определенный штрих-код в этот документ со сканером, который вы хотите настроить. Это штрих-код под названием "Режим последовательной эмуляции".

Для этого сканера требуется драйвер для эмуляции последовательного порта. Я нашел инструкции по внедрению и необходимые драйверы здесь (на вкладке "программное обеспечение"). Загрузите пакет под названием "Последовательный USB-драйвер Honeywell Scanning and Mobility (HSM)". В PDF-файле под названием "Руководство по началу работы с последовательным драйвером HSM USB" были инструкции.

Если вы не знакомы с API javax.comm. Пожалуйста, прочтите введение в этом примере Рика Проктора - там рассказывается вам, где взять банку и куда поместить файлы (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);
        }
    };
}

Ответ 2 · рейтинг 9 · prunge

Сканер штрих-кода, который я использовал, действовал как клавиатурное устройство (в операционной системе он отображался как USB-устройство HID-клавиатуры). Когда штрих-код был отсканирован, он отправил код, как если бы он был напечатан. Никаких специальных API для взаимодействия с ним не требовалось.

Ответ 3 · рейтинг 7 · Pavel Kucera

Я знаю, что это довольно старая тема, но поиск может привести вас туда.

Это можно рассматривать как дополнение к ответу Джеронимо:

Для ОС Linux нет необходимости устанавливать драйверы для сканеров штрих-кода в режиме эмуляции последовательного порта, поскольку имеется встроенная поддержка последовательных портов USB. Мы используем несколько типов сканеров Honeywell, и все они работают "из коробки", эти сканеры в последовательной эмуляции отображаются в наших системах как /dev/ttyACM0, /dev/ttyACM1 и т. д.

Недавно мы перешли с javax.comm на jssc в качестве java-библиотеки для интерфейса последовательных портов. Если я хорошо помню, в 64-битной системе Windows 7 библиотека javax.comm не может читать или записывать из/в последовательный порт, а jssc имеет очень похожий API.

Ответ 4 · philosowaffle

Я понимаю, что это был старый вопрос, но решил добавить дополнительное решение для имитации ввода сканера штрих-кода. Это решение работает только для имитации ввода сканером данных с клавиатуры.

Поскольку сканеры часто используют ввод с клавиатуры, мы можем имитировать это с помощью скрипта 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] и [BC200015] тем, что вы ожидаете от сканера.

Перевод вопроса и ответов сообщества Stack Overflow, лицензия CC BY-SA. Оригинал на Stack Overflow.

Похожие материалы