// Chromis POS - The New Face of Open Source POS // Copyright (c) 2015 // http://www.chromis.co.uk // // This file is part of Chromis POS // // Chromis POS is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Chromis POS is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Chromis POS. If not, see <http://www.gnu.org/licenses/>. package uk.chromis.pos.scale; import gnu.io.*; import java.awt.Component; import java.awt.Dimension; import java.io.*; import java.util.TooManyListenersException; import uk.chromis.pos.forms.AppLocal; import java.util.logging.Logger; import java.awt.Font; import java.util.logging.Level; import javax.swing.plaf.FontUIResource; import javax.swing.JOptionPane; import javax.swing.JDialog; import javax.swing.JLabel; import javax.swing.UIManager; /** * * */ public class ScaleAdam implements Scale, SerialPortEventListener { private static final Logger logger = Logger.getLogger("uk.chromis.pos.scale.ScaleAdam"); private CommPortIdentifier m_PortId; private NRSerialPort m_CommPort; private String m_sPortScale; private OutputStream m_out; private InputStream m_in; private static final int SCALE_READY = 0; private static final int SCALE_READING = 1; private static final int SCALE_USERPRESSEDOK = 2; private static final int SCALE_USERPRESSEDCANCEL = 3; private static int SCALE_ERROR = -1; private String m_WeightBuffer; private int m_iStatusScale; private Component mParent; private Font m_OriginalFont; private JDialog m_Dialog; /** Creates a new instance of ScaleComm * @param sPortPrinter */ public ScaleAdam(String sPortPrinter, Component parent ) { m_sPortScale = sPortPrinter; m_out = null; m_in = null; m_iStatusScale = SCALE_READY; m_WeightBuffer = ""; mParent = parent; } private void showDialog() { // Get details of the original font before we change it otherwise all dialogboxes will use new settings JOptionPane pane = new JOptionPane(); Font originalFont=pane.getFont(); UIManager.put("OptionPane.buttonFont", new FontUIResource(new Font("ARIAL",Font.PLAIN,20))); String message = AppLocal.getIntString("scale.weighitem"); JLabel FontText = new JLabel(message); FontText.setFont (new Font ( "Arial", Font.BOLD, 36) ); JOptionPane newpane = new JOptionPane( FontText, JOptionPane.PLAIN_MESSAGE, JOptionPane.CANCEL_OPTION, null, new Object[]{"Cancel"} ); newpane.setPreferredSize( new Dimension(450,150)); m_Dialog = newpane.createDialog("Use Scales"); m_Dialog.setVisible( true ); // Return to default settings UIManager.put("OptionPane.buttonFont", new FontUIResource(new Font(originalFont.getName(),originalFont.getStyle(),originalFont.getSize()))); if( m_iStatusScale == SCALE_READING ) { // User must have pressed cancel changeStatus( SCALE_USERPRESSEDCANCEL ); } } private void backgroundReadInput( final int nTimeout ) { Thread readThread = new Thread() { public void run() { readInput(nTimeout); } }; readThread.start(); } private void readInput( int nTimeout ) { while( --nTimeout > 0 && m_iStatusScale == SCALE_READING ) { try { synchronized (this) { wait(1000); } } catch (InterruptedException ex) { changeStatus( SCALE_ERROR ); } } if( m_iStatusScale == SCALE_READING ) { // must have timed out changeStatus( SCALE_ERROR ); } } private void changeStatus( int status ) { m_iStatusScale = status; if( status != SCALE_READING ) { if( m_Dialog != null ) m_Dialog.setVisible(false); } } /** * * @return */ @Override public Double readWeight() { synchronized(this) { m_iStatusScale = SCALE_READING; m_WeightBuffer = ""; try { if (m_out == null) { m_CommPort = new NRSerialPort(m_sPortScale, 4800); m_CommPort.connect(); m_CommPort.addEventListener(this); m_CommPort.notifyOnDataAvailable(true); m_out = m_CommPort.getOutputStream(); m_in = m_CommPort.getInputStream(); } } catch ( TooManyListenersException e ) { logger.log(Level.SEVERE, "Port exception", e ); changeStatus( SCALE_ERROR ); } backgroundReadInput( 60 ); } showDialog(); synchronized(this) { try { if (m_out != null) m_out.close(); if (m_in != null) m_in.close(); if (m_CommPort != null) { m_CommPort.removeEventListener(); m_CommPort.disconnect(); } } catch ( IOException e ) { } m_out = null; m_in = null; m_CommPort = null; m_PortId = null; if( m_Dialog != null ) m_Dialog.setVisible(false); m_Dialog = null; if (m_iStatusScale == SCALE_READY && m_WeightBuffer != null && m_WeightBuffer.isEmpty() == false ) { logger.log(Level.INFO, "Scale ready", m_WeightBuffer ); double dWeight = Double.parseDouble( m_WeightBuffer ); return dWeight; } else { logger.log(Level.WARNING, "Scale no data", m_WeightBuffer ); // Timed out looking for weight or error return null; } } } private void write(byte[] data) { synchronized (this) { try { m_out.write(data); } catch ( IOException e) { assert( false ); } } } /** * * @param e */ @Override public void serialEvent(SerialPortEvent e) { // Determine type of event. switch (e.getEventType()) { case SerialPortEvent.BI: case SerialPortEvent.OE: case SerialPortEvent.FE: case SerialPortEvent.PE: case SerialPortEvent.CD: case SerialPortEvent.CTS: case SerialPortEvent.DSR: case SerialPortEvent.RI: case SerialPortEvent.OUTPUT_BUFFER_EMPTY: break; case SerialPortEvent.DATA_AVAILABLE: synchronized (this) { try { while (m_in.available() > 0) { int b = m_in.read(); logger.log(Level.WARNING, "Scale sent", Character.toString ((char) b) ); if (b == 0x000D) { // CR ASCII // End of Line synchronized (this) { changeStatus( SCALE_READY ); notifyAll(); } } else { if( b == 0x2e || (b >= 0x30 && b <= 0x39 ) ) { // Ascii for period or 0-9 m_WeightBuffer = m_WeightBuffer + Character.toString ((char) b); } } } } catch (IOException eIO) { logger.log(Level.SEVERE, "Scale io error", eIO ); changeStatus( SCALE_ERROR ); } } break; } } }