Created
April 13, 2022 16:35
-
-
Save giorgiofellipe/138cd4f4b868d855565c5815e3e8d0c4 to your computer and use it in GitHub Desktop.
PrinterProtocolAdapter.class
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// Source code recreated from a .class file by IntelliJ IDEA | |
// (powered by Fernflower decompiler) | |
// | |
package com.datecs.api.printer; | |
import java.io.IOException; | |
import java.io.InputStream; | |
import java.io.OutputStream; | |
public final class ProtocolAdapter { | |
private static final int MAX_PACKET_SIZE = 2048; | |
private static final int DEFAULT_TIMEOUT = 1000; | |
private static final int HEADER_SIZE = 4; | |
private static final int PACKET_SIZE = 2048; | |
private static final int DATA_SIZE = 2044; | |
private static final int EVENT_BARCODE = 1; | |
private static final int EVENT_MSR = 2; | |
private static final int EVENT_PAPER_IN = 4; | |
private static final int EVENT_ENCRYPTED_MSR = 16; | |
private static final int EVENT_PAPER_OUT = 32; | |
private static final int STATUS_FAILED = 1; | |
private static final int STATUS_FULL = 2; | |
private static final int STATUS_INVALID = 4; | |
private static final int STATUS_LOWBATTERY = 8; | |
private static final int STATUS_OVERHEATED = 16; | |
private static final int STATUS_NOPAPER = 32; | |
private static final int COMMAND_OPEN = 0; | |
private static final int COMMAND_CLOSE = 1; | |
private static final int COMMAND_SEND = 2; | |
private static final int COMMAND_REQUEST = 3; | |
private static final int COMMAND_GETSTATUS = 4; | |
private static final int COMMAND_SETPORT = 5; | |
public static final int CHANNEL_PRINTER = 1; | |
public static final int CHANNEL_EMSR = 15; | |
public static final int CHANNEL_UNIVERSAL_READER = 16; | |
public static final int CHANNEL_RFID = 13; | |
private InputStream mBaseInputStream; | |
private OutputStream mBaseOutputStream; | |
private IOException mLastError; | |
private InputStream mRawInputStream; | |
private OutputStream mRawOutputStream; | |
private byte[] mDataBuffer; | |
private int mDataBufferLen; | |
private boolean mProtoEnabled; | |
private ProtocolAdapter.BarcodeListener mBarcodeListener; | |
private ProtocolAdapter.CardListener mCardListener; | |
private ProtocolAdapter.PrinterListener mPrinterListener; | |
private boolean mLastPaperState; | |
private boolean mLastBatteryState; | |
private boolean mLastThermalHeadState; | |
private long mLastAccessTime; | |
private int mLastStatus; | |
private static boolean sDebug = false; | |
private static final byte[] EMPTY = new byte[0]; | |
public ProtocolAdapter(InputStream in, OutputStream out) throws IOException { | |
if (in == null) { | |
throw new NullPointerException("The in is null"); | |
} else if (out == null) { | |
throw new NullPointerException("The out is null"); | |
} else { | |
this.mBaseInputStream = in; | |
this.mBaseOutputStream = out; | |
this.mDataBuffer = new byte[4096]; | |
this.mDataBufferLen = 0; | |
this.mLastPaperState = false; | |
this.mLastBatteryState = false; | |
this.mLastThermalHeadState = false; | |
this.mLastAccessTime = System.currentTimeMillis(); | |
Thread t = new Thread(new Runnable() { | |
public void run() { | |
byte[] buffer = new byte[2048]; | |
try { | |
while(ProtocolAdapter.this.mLastError == null) { | |
int bytesRead = ProtocolAdapter.this.read(buffer, 0, buffer.length); | |
synchronized(ProtocolAdapter.this.mDataBuffer) { | |
int length = Math.min(ProtocolAdapter.this.mDataBuffer.length - ProtocolAdapter.this.mDataBufferLen, bytesRead); | |
System.arraycopy(buffer, 0, ProtocolAdapter.this.mDataBuffer, ProtocolAdapter.this.mDataBufferLen, length); | |
ProtocolAdapter var10000 = ProtocolAdapter.this; | |
var10000.mDataBufferLen = var10000.mDataBufferLen + length; | |
} | |
try { | |
Thread.sleep(10L); | |
} catch (InterruptedException var5) { | |
} | |
} | |
} catch (IOException var7) { | |
if (ProtocolAdapter.sDebug) { | |
var7.printStackTrace(); | |
} | |
if (ProtocolAdapter.this.mLastError == null) { | |
ProtocolAdapter.this.mLastError = var7; | |
} | |
} | |
} | |
}); | |
t.start(); | |
this.mProtoEnabled = this.getProtocolMode(); | |
} | |
} | |
public synchronized void close() { | |
this.mLastError = new IOException("The object is closed"); | |
try { | |
this.mBaseInputStream.close(); | |
} catch (IOException var3) { | |
} | |
try { | |
this.mBaseOutputStream.close(); | |
} catch (IOException var2) { | |
} | |
} | |
public static void setDebug(boolean on) { | |
sDebug = on; | |
} | |
private void debug(String text) { | |
if (sDebug) { | |
System.out.println(text); | |
} | |
} | |
private void debug(String text, byte[] buffer, int offset, int count) { | |
if (sDebug) { | |
this.debug("<ProtocolAdapter> " + text + byteArrayToHexString(buffer, offset, count) + "(" + count + ")"); | |
} | |
} | |
private static final String byteArrayToHexString(byte[] data, int offset, int length) { | |
char[] hex = new char[]{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'}; | |
char[] buf = new char[length * 3]; | |
int offs = 0; | |
for(int i = 0; i < length; ++i) { | |
buf[offs++] = hex[data[offset + i] >> 4 & 15]; | |
buf[offs++] = hex[data[offset + i] >> 0 & 15]; | |
buf[offs++] = ' '; | |
} | |
return new String(buf, 0, offs); | |
} | |
private void write(byte[] b, int offset, int length) throws IOException { | |
this.mBaseOutputStream.write(b, offset, length); | |
this.mBaseOutputStream.flush(); | |
this.debug(">> ", b, offset, length); | |
} | |
private int read(byte[] buffer, int offset, int length) throws IOException { | |
int bytesRead = this.mBaseInputStream.read(buffer, offset, length); | |
if (bytesRead < 0) { | |
throw new IOException("The end of the stream is reached"); | |
} else if (bytesRead > length) { | |
throw new IOException("Invalid stream result " + bytesRead); | |
} else { | |
if (bytesRead > 0) { | |
this.debug("<< ", buffer, offset, bytesRead); | |
} | |
return bytesRead; | |
} | |
} | |
private void request(int length, int timeout) throws IOException { | |
long endTime = System.currentTimeMillis() + (long)timeout; | |
while(this.mDataBufferLen < length) { | |
if (this.mLastError != null) { | |
throw this.mLastError; | |
} | |
if (endTime < System.currentTimeMillis()) { | |
throw new IOException("Timeout"); | |
} | |
try { | |
Thread.sleep(10L); | |
} catch (InterruptedException var6) { | |
} | |
} | |
} | |
private void consume(int length) { | |
synchronized(this.mDataBuffer) { | |
if (length > this.mDataBufferLen) { | |
length = this.mDataBufferLen; | |
} | |
this.mDataBufferLen -= length; | |
System.arraycopy(this.mDataBuffer, length, this.mDataBuffer, 0, this.mDataBufferLen); | |
} | |
} | |
private int pending() { | |
synchronized(this.mDataBuffer) { | |
return this.mDataBufferLen; | |
} | |
} | |
private boolean getProtocolMode() throws IOException { | |
this.debug("Get if printer is into protocol mode"); | |
do { | |
this.consume(2048); | |
try { | |
Thread.sleep(50L); | |
} catch (InterruptedException var3) { | |
} | |
} while(this.pending() > 0); | |
this.writePacket(1, 2); | |
try { | |
this.request(4, 500); | |
} catch (IOException var2) { | |
this.debug("Protocol mode enabled"); | |
return false; | |
} | |
this.consume(2048); | |
this.debug("Protocol mode disabled"); | |
return true; | |
} | |
private void raiseReadBarcode() { | |
final ProtocolAdapter.BarcodeListener l = this.mBarcodeListener; | |
if (l != null) { | |
(new Thread(new Runnable() { | |
public void run() { | |
l.onReadBarcode(); | |
} | |
})).start(); | |
} | |
} | |
private void raiseReadCard(final boolean encrypted) { | |
final ProtocolAdapter.CardListener l = this.mCardListener; | |
if (l != null) { | |
(new Thread(new Runnable() { | |
public void run() { | |
l.onReadCard(encrypted); | |
} | |
})).start(); | |
} | |
} | |
private void raiseBatteryStateChanged(final boolean state) { | |
final ProtocolAdapter.PrinterListener l = this.mPrinterListener; | |
if (l != null && this.mLastBatteryState != state) { | |
this.mLastBatteryState = state; | |
(new Thread(new Runnable() { | |
public void run() { | |
l.onBatteryStateChanged(state); | |
} | |
})).start(); | |
} | |
} | |
private void raisePaperStateChanged(final boolean state) { | |
final ProtocolAdapter.PrinterListener l = this.mPrinterListener; | |
if (l != null && this.mLastPaperState != state) { | |
this.mLastPaperState = state; | |
(new Thread(new Runnable() { | |
public void run() { | |
l.onPaperStateChanged(state); | |
} | |
})).start(); | |
} | |
} | |
private void raiseThermalHeadStateChanged(final boolean state) { | |
final ProtocolAdapter.PrinterListener l = this.mPrinterListener; | |
if (l != null && this.mLastThermalHeadState != state) { | |
this.mLastThermalHeadState = state; | |
(new Thread(new Runnable() { | |
public void run() { | |
l.onThermalHeadStateChanged(state); | |
} | |
})).start(); | |
} | |
} | |
private void processEvent(int event) { | |
if ((event & 1) != 0) { | |
this.raiseReadBarcode(); | |
} | |
if ((event & 2) != 0) { | |
this.raiseReadCard(false); | |
} | |
if ((event & 4) != 0) { | |
this.raisePaperStateChanged(true); | |
} | |
if ((event & 32) != 0) { | |
this.raisePaperStateChanged(false); | |
} | |
if ((event & 16) != 0) { | |
this.raiseReadCard(true); | |
} | |
} | |
private void suspendTransmit(int time) { | |
long elapsed = System.currentTimeMillis() - this.mLastAccessTime; | |
if (elapsed < (long)time) { | |
try { | |
Thread.sleep((long)time - elapsed); | |
} catch (InterruptedException var5) { | |
} | |
} | |
} | |
private void writePacket(int channel, int command, byte[] data, int offset, int length) throws IOException { | |
byte[] buffer = new byte[4 + length]; | |
buffer[0] = (byte)channel; | |
buffer[1] = (byte)command; | |
buffer[2] = (byte)(length >> 8); | |
buffer[3] = (byte)(length & 255); | |
System.arraycopy(data, offset, buffer, 4, length); | |
this.write(buffer, 0, buffer.length); | |
} | |
private void writePacket(int channel, int command, byte[] data) throws IOException { | |
this.writePacket(channel, command, data, 0, data.length); | |
} | |
private void writePacket(int channel, int command) throws IOException { | |
this.writePacket(channel, command, new byte[0]); | |
} | |
private byte[] readPacket(int reqChannel) throws IOException { | |
while(true) { | |
if (this.mDataBufferLen > 0 && this.mDataBuffer[0] == 43) { | |
this.consume(1); | |
} else { | |
this.request(4, 1000); | |
int channel = this.mDataBuffer[0] & 255; | |
int status = this.mDataBuffer[1] & 255; | |
int length = (this.mDataBuffer[2] & 255) << 8 | this.mDataBuffer[3] & 255; | |
byte[] data = EMPTY; | |
if ((channel & 128) == 0) { | |
this.processEvent(length); | |
length = 0; | |
} else if (length > 0) { | |
this.request(4 + length, 1000); | |
data = new byte[length]; | |
System.arraycopy(this.mDataBuffer, 4, data, 0, data.length); | |
} | |
this.consume(4 + length); | |
channel ^= 128; | |
if (channel == reqChannel) { | |
this.mLastStatus = status; | |
if (channel == 1) { | |
if ((status & 1) > 0) { | |
throw new IOException("Command failed"); | |
} | |
if ((status & 4) > 0) { | |
throw new IOException("Invalid command"); | |
} | |
if ((status & 8) > 0) { | |
this.raiseBatteryStateChanged(false); | |
} else { | |
this.raiseBatteryStateChanged(false); | |
} | |
if ((status & 16) > 0) { | |
this.raiseThermalHeadStateChanged(true); | |
} else { | |
this.raiseThermalHeadStateChanged(false); | |
} | |
if ((status & 32) > 0) { | |
this.raisePaperStateChanged(true); | |
} else { | |
this.raisePaperStateChanged(false); | |
} | |
} | |
return data; | |
} | |
} | |
} | |
} | |
private synchronized void writeToChannel(int reqChannel, byte[] buffer, int offset, int length) throws IOException { | |
this.suspendTransmit(10); | |
while(length > 0) { | |
int chunkSize = Math.min(length, 2044); | |
this.writePacket(reqChannel, 2, buffer, offset, chunkSize); | |
this.readPacket(reqChannel); | |
if ((this.mLastStatus & 2) != 0) { | |
try { | |
Thread.sleep(50L); | |
} catch (InterruptedException var7) { | |
var7.printStackTrace(); | |
} | |
} else { | |
offset += chunkSize; | |
length -= chunkSize; | |
} | |
} | |
this.mLastAccessTime = System.currentTimeMillis(); | |
} | |
private synchronized int readFromChannel(int reqChannel, byte[] buffer, int offset, int length) throws IOException { | |
this.suspendTransmit(10); | |
this.writePacket(reqChannel, 3); | |
byte[] result = this.readPacket(reqChannel); | |
if (result.length > length) { | |
throw new IOException("Insufficient buffer size"); | |
} else { | |
this.mLastAccessTime = System.currentTimeMillis(); | |
System.arraycopy(result, 0, buffer, offset, result.length); | |
return result.length; | |
} | |
} | |
public void setBarcodeListener(ProtocolAdapter.BarcodeListener listener) { | |
this.mBarcodeListener = listener; | |
} | |
public void setCardListener(ProtocolAdapter.CardListener listener) { | |
this.mCardListener = listener; | |
} | |
public void setPrinterListener(ProtocolAdapter.PrinterListener listener) { | |
this.mPrinterListener = listener; | |
} | |
public boolean isProtocolEnabled() { | |
return this.mProtoEnabled; | |
} | |
public ProtocolAdapter.Channel getChannel(int channel) { | |
if (!this.isProtocolEnabled()) { | |
throw new IllegalAccessError("Protocol mode is not supported"); | |
} else { | |
return new ProtocolAdapter.Channel(channel, (ProtocolAdapter.Channel)null); | |
} | |
} | |
public InputStream getRawInputStream() { | |
if (this.mRawInputStream == null) { | |
this.mRawInputStream = new InputStream() { | |
public int available() throws IOException { | |
if (ProtocolAdapter.this.mLastError != null) { | |
throw ProtocolAdapter.this.mLastError; | |
} else { | |
return ProtocolAdapter.this.pending(); | |
} | |
} | |
public int read() throws IOException { | |
byte[] buffer = new byte[1]; | |
this.read(buffer); | |
return buffer[0] & 255; | |
} | |
public int read(byte[] buffer, int offset, int length) throws IOException { | |
boolean var4 = false; | |
int bytesAvailable; | |
while((bytesAvailable = this.available()) == 0) { | |
if (ProtocolAdapter.this.mLastError != null) { | |
throw ProtocolAdapter.this.mLastError; | |
} | |
try { | |
Thread.sleep(10L); | |
} catch (InterruptedException var6) { | |
var6.printStackTrace(); | |
} | |
} | |
length = Math.min(length, bytesAvailable); | |
System.arraycopy(ProtocolAdapter.this.mDataBuffer, 0, buffer, offset, length); | |
ProtocolAdapter.this.consume(length); | |
return length; | |
} | |
public int read(byte[] buffer) throws IOException { | |
return this.read(buffer, 0, buffer.length); | |
} | |
public void close() throws IOException { | |
ProtocolAdapter.this.mBaseInputStream.close(); | |
} | |
}; | |
} | |
return this.mRawInputStream; | |
} | |
public OutputStream getRawOutputStream() { | |
if (this.mRawOutputStream == null) { | |
this.mRawOutputStream = this.mBaseOutputStream; | |
} | |
return this.mRawOutputStream; | |
} | |
public interface BarcodeListener { | |
void onReadBarcode(); | |
} | |
public interface CardListener { | |
void onReadCard(boolean var1); | |
} | |
public class Channel { | |
private int mChannel; | |
private boolean mSuspended; | |
public void suspend() { | |
this.mSuspended = true; | |
} | |
public void resume() { | |
this.mSuspended = false; | |
} | |
private Channel(int channel) { | |
this.mChannel = channel; | |
} | |
public int getChannel() { | |
return this.mChannel; | |
} | |
public void open() throws IOException { | |
synchronized(ProtocolAdapter.this) { | |
ProtocolAdapter.this.writePacket(this.mChannel, 0); | |
ProtocolAdapter.this.readPacket(this.mChannel); | |
} | |
} | |
public void close() throws IOException { | |
synchronized(ProtocolAdapter.this) { | |
ProtocolAdapter.this.writePacket(this.mChannel, 1); | |
ProtocolAdapter.this.readPacket(this.mChannel); | |
} | |
} | |
public void setChannel(int speed, int flow) throws IOException { | |
byte[] buffer = new byte[]{(byte)speed, (byte)flow}; | |
synchronized(ProtocolAdapter.this) { | |
ProtocolAdapter.this.writePacket(this.mChannel, 5, buffer, 0, buffer.length); | |
ProtocolAdapter.this.readPacket(this.mChannel); | |
} | |
} | |
public void setLedMode(int mode) throws IOException { | |
synchronized(ProtocolAdapter.this) { | |
switch(mode) { | |
case 0: | |
ProtocolAdapter.this.writePacket(this.mChannel, 6); | |
break; | |
case 1: | |
ProtocolAdapter.this.writePacket(this.mChannel, 5, new byte[]{1}); | |
break; | |
case 2: | |
ProtocolAdapter.this.writePacket(this.mChannel, 5); | |
} | |
ProtocolAdapter.this.readPacket(this.mChannel); | |
} | |
} | |
public byte[] getStatus() throws IOException { | |
synchronized(ProtocolAdapter.this) { | |
ProtocolAdapter.this.writePacket(this.mChannel, 4); | |
return ProtocolAdapter.this.readPacket(this.mChannel); | |
} | |
} | |
public InputStream getInputStream() { | |
return new InputStream() { | |
private byte[] mBuffer = new byte[2044]; | |
private int mOffset = 0; | |
private int mLength = 0; | |
private IOException mIOException; | |
public synchronized int available() throws IOException { | |
if (this.mIOException != null) { | |
throw this.mIOException; | |
} else { | |
if (this.mLength == 0) { | |
try { | |
this.mOffset = 0; | |
if (Channel.this.mSuspended) { | |
this.mLength = 0; | |
} else { | |
this.mLength = ProtocolAdapter.this.readFromChannel(Channel.this.mChannel, this.mBuffer, 0, this.mBuffer.length); | |
} | |
} catch (IOException var2) { | |
this.mIOException = var2; | |
throw var2; | |
} | |
} | |
return this.mLength; | |
} | |
} | |
public synchronized int read(byte[] b, int off, int len) throws IOException { | |
while(this.available() == 0) { | |
try { | |
Thread.sleep(10L); | |
} catch (InterruptedException var5) { | |
} | |
} | |
int chunkSize = Math.min(this.mLength, len); | |
System.arraycopy(this.mBuffer, this.mOffset, b, off, chunkSize); | |
this.mOffset += chunkSize; | |
this.mLength -= chunkSize; | |
return chunkSize; | |
} | |
public synchronized int read(byte[] b) throws IOException { | |
return this.read(b, 0, b.length); | |
} | |
public synchronized int read() throws IOException { | |
byte[] b = new byte[1]; | |
this.read(b); | |
return b[0] & 255; | |
} | |
public void close() throws IOException { | |
if (this.mIOException != null) { | |
this.mIOException = new IOException("The stream is closed"); | |
} | |
} | |
}; | |
} | |
public OutputStream getOutputStream() { | |
return new OutputStream() { | |
private IOException mIOException; | |
public void write(byte[] b, int off, int len) throws IOException { | |
if (this.mIOException != null) { | |
throw this.mIOException; | |
} else { | |
try { | |
ProtocolAdapter.this.writeToChannel(Channel.this.mChannel, b, off, len); | |
} catch (IOException var5) { | |
this.mIOException = var5; | |
throw var5; | |
} | |
} | |
} | |
public void write(byte[] b) throws IOException { | |
this.write(b, 0, b.length); | |
} | |
public void write(int b) throws IOException { | |
this.write(new byte[]{(byte)b}); | |
} | |
public void close() throws IOException { | |
if (this.mIOException != null) { | |
this.mIOException = new IOException("The stream is closed"); | |
} | |
} | |
}; | |
} | |
} | |
public interface PrinterListener { | |
void onBatteryStateChanged(boolean var1); | |
void onThermalHeadStateChanged(boolean var1); | |
void onPaperStateChanged(boolean var1); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment