Skip to content

Instantly share code, notes, and snippets.

@giorgiofellipe
Created April 13, 2022 16:35
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save giorgiofellipe/138cd4f4b868d855565c5815e3e8d0c4 to your computer and use it in GitHub Desktop.
Save giorgiofellipe/138cd4f4b868d855565c5815e3e8d0c4 to your computer and use it in GitHub Desktop.
PrinterProtocolAdapter.class
//
// 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