Skip to content

Commit 481f232

Browse files
committed
Bug Fixes And Enhancements
Enhancements: - Support for PINPad added. Bug fixes: - Handling of DataCount corrected. - Program exit handling corrected to ensure that DataCountThread will always be terminated. - String representation of byte arrays generated via byteArrayToHexString or byteArrayToAsciiString for easier conversion between values and their string representation now.
1 parent 752e513 commit 481f232

6 files changed

Lines changed: 719 additions & 45 deletions

File tree

src/SPF_Test/CommonController.java

Lines changed: 26 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -351,33 +351,33 @@ private class DataCountUpdater extends Thread {
351351
@Override
352352
public void run() {
353353
long timeout = SyncObject.INFINITE;
354+
Integer oldcount = null;
354355
while (Control.getState() != JposConst.JPOS_S_CLOSED) {
355356
CheckWaiter.suspend(timeout);
356357
try {
357358
timeout = Control.getDeviceEnabled() ? 100 : SyncObject.INFINITE;
358359
} catch (JposException e) {
359360
timeout = SyncObject.INFINITE;
360361
}
362+
Integer count;
363+
try {
364+
Method getDataCount = Control.getClass().getMethod("getDataCount");
365+
count = (Integer) getDataCount.invoke(Control);
366+
} catch (Exception e) {
367+
count = null;
368+
}
361369
final long tio = timeout;
362-
Platform.runLater(new Runnable() {
363-
@Override
364-
public void run() {
365-
try {
366-
if (tio > 0) {
367-
Method getDataCount = Class.forName(Control.getClass().getName()).getMethod("getDataCount");
368-
DataCount.setText("DataCount: " + (Integer) getDataCount.invoke(Control));
369-
}
370-
} catch (Exception e) {
371-
DataCount.setText("");
370+
final Integer datacount = count;
371+
boolean equal = count == null ? oldcount == null : count.equals(oldcount);
372+
if (!equal) {
373+
Platform.runLater(new Runnable() {
374+
@Override
375+
public void run() {
376+
DataCount.setText(datacount == null ? "" : "DataCount: " + datacount);
377+
updateGui();
372378
}
373-
int i = JposConst.JPOS_EL_INPUT_DATA; // 3
374-
i = JposConst.JPOS_EL_INPUT; // 2
375-
i = JposConst.JPOS_EL_OUTPUT; // 1
376-
i = JposConst.JPOS_ER_CONTINUEINPUT; // 13
377-
i = JposConst.JPOS_ER_CLEAR; // 12
378-
i = JposConst.JPOS_ER_RETRY; // 11
379-
}
380-
});
379+
});
380+
}
381381
}
382382
}
383383
}
@@ -925,33 +925,16 @@ void updateGui() {
925925
String result = "";
926926
switch (Conversion) {
927927
case Hexadecimal: {
928-
for (byte b : data) {
929-
result += new String(new char[]{
930-
"0123456789ABCDEF".charAt((b & 0xf0) >> 4),
931-
"0123456789ABCDEF".charAt(b & 0xf)
932-
});
933-
if (result.length() >= MaxConversionLength - 1)
934-
break;
935-
}
936-
row.setValue(result);
928+
if (data.length > MaxConversionLength / 2)
929+
data = Arrays.copyOf(data, MaxConversionLength / 2);
930+
row.setValue(byteArrayToHexString(data, data.length, false, 0));
937931
break;
938932
}
939933
case Ascii: {
940-
for (byte b : data) {
941-
if ((b & 0xff) >= 0x20 && (b & 0xff) < 0x7f && b != (byte) '\\' && b != (byte) ']') {
942-
result += new String(new char[]{(char) (b & 0xff)});
943-
} else if (b == (byte) '\\' || b == (byte) ']') {
944-
result += "\\" + new String(new byte[]{b});
945-
} else {
946-
result += "\\x" + new String(new char[]{
947-
"0123456789ABCDEF".charAt((b & 0xf0) >> 4),
948-
"0123456789ABCDEF".charAt(b & 0xf)
949-
});
950-
}
951-
if (result.length() >= MaxConversionLength - 1)
952-
break;
953-
}
954-
row.setValue(result);
934+
if (data.length > MaxConversionLength)
935+
data = Arrays.copyOf(data, MaxConversionLength);
936+
result = byteArrayToAsciiString(data, MaxConversionLength * 4);
937+
row.setValue(result.length() > MaxConversionLength ? result.substring(0, MaxConversionLength) : result);
955938
break;
956939
}
957940
case Decoded: {
@@ -1213,6 +1196,7 @@ public void initialize(URL url, ResourceBundle resourceBundle) {
12131196
DeviceControl resource = (DeviceControl)(((DeviceControl.DeviceResources)resourceBundle).getContents()[0][0]);
12141197
Control = resource.getControl();
12151198
LogicalDeviceName = resource.getName();
1199+
resource.Controller = this;
12161200
Properties.getItems().add(new PropertyTableRow("State", new StateValues().getSymbol(Control.getState()), new StateValues()));
12171201
Properties.getItems().add(new PropertyTableRow("PowerState", "", new PowerStateValues()));
12181202
TableColumn<PropertyTableRow, String> column = new TableColumn<>("Name");

src/SPF_Test/DeviceControl.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,11 @@ public class DeviceControl {
4545
*/
4646
Parent Gui = null;
4747

48+
/**
49+
* The CommonController that handles Control
50+
*/
51+
CommonController Controller = null;
52+
4853
/**
4954
* Retrieves JavaPOS control belonging to this DeviceControl instance.
5055
*/
@@ -240,6 +245,9 @@ static void loadDevices(String jposXml, Controller control) {
240245
} else if (category.equals("MSR")) {
241246
actdev.Control = new MSR();
242247
actdev.Gui = FXMLLoader.load(control.getClass().getResource("MSR.fxml"), new DeviceResources(actdev));
248+
} else if (category.equals("PINPad")) {
249+
actdev.Control = new PINPad();
250+
actdev.Gui = FXMLLoader.load(control.getClass().getResource("PINPad.fxml"), new DeviceResources(actdev));
243251
} else if (category.equals("POSKeyboard")) {
244252
actdev.Control = new POSKeyboard();
245253
actdev.Gui = FXMLLoader.load(control.getClass().getResource("POSKeyboard.fxml"), new DeviceResources(actdev));

src/SPF_Test/Main.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,8 @@ public static void main(String[] args) {
5151
for (DeviceControl dev : DeviceControl.Devices.values()) {
5252
if (dev.getControl() != null && dev.getControl().getState() != JposConst.JPOS_S_CLOSED) {
5353
try {
54-
dev.getControl().close();
55-
} catch (JposException e) {
54+
dev.Controller.close(null);
55+
} catch (Throwable e) {
5656
e.printStackTrace();
5757
}
5858
}

src/SPF_Test/PINPad.fxml

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
3+
<?import java.lang.*?>
4+
<?import java.util.*?>
5+
<?import javafx.scene.*?>
6+
<?import javafx.scene.control.*?>
7+
<?import javafx.scene.layout.*?>
8+
9+
<!--
10+
~ Copyright 2023 Martin Conrad
11+
~ <p>
12+
~ Licensed under the Apache License, Version 2.0 (the "License");
13+
~ you may not use this file except in compliance with the License.
14+
~ You may obtain a copy of the License at
15+
~ <p>
16+
~ http://www.apache.org/licenses/LICENSE-2.0
17+
~ <p>
18+
~ Unless required by applicable law or agreed to in writing, software
19+
~ distributed under the License is distributed on an "AS IS" BASIS,
20+
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21+
~ See the License for the specific language governing permissions and
22+
~ limitations under the License.
23+
~
24+
-->
25+
26+
<AnchorPane xmlns="http://javafx.com/javafx"
27+
xmlns:fx="http://javafx.com/fxml"
28+
fx:controller="SPF_Test.PINPadController"
29+
prefHeight="540.0" prefWidth="980.0">
30+
<CheckBox fx:id="DeviceEnabled" text="DeviceEnabled" layoutY="5" onAction="#setDeviceEnabled"/>
31+
<CheckBox fx:id="FreezeEvents" text="FreezeEvents" layoutX="105" layoutY="5" onAction="#setFreezeEvents"/>
32+
<ComboBox fx:id="PowerNotify" prefWidth="145" layoutX="210" editable="true" onAction="#setPowerNotify"/>
33+
<Label text="PowerNotify" layoutX="360" layoutY="5"/>
34+
<ComboBox fx:id="CurrencyDigits" layoutX="435" onAction="#setCurrencyDigits" prefWidth="50"/>
35+
<Label text="Currency Digits" layoutX="490" layoutY="5"/>
36+
<CheckBox fx:id="DataEventEnabled" text="DataEventEnabled" layoutX="570" onAction="#setDataEventEnabled"/>
37+
<CheckBox fx:id="PINEntryEnabled" layoutX="695" disable="true"/>
38+
<Label text="PINEntryEnabled" layoutX="715"/>
39+
<Label fx:id="DataCount" layoutX="810" text="DataCount: 0"/>
40+
<TableView fx:id="Properties" layoutX="570" layoutY="19" prefWidth="410" prefHeight="96"/>
41+
<Button text="Open" layoutY="35" onAction="#open" prefWidth="70"/>
42+
<Button text="Claim" layoutX="80" layoutY="35" onAction="#claim" prefWidth="70"/>
43+
<ComboBox fx:id="claim_timeout" prefWidth="70" layoutX="80" layoutY="60" promptText="timeout" editable="true"/>
44+
<Button text="Release" layoutX="160" layoutY="35" onAction="#release" prefWidth="70"/>
45+
<Button text="Close" layoutX="240" layoutY="35" onAction="#close" prefWidth="70"/>
46+
<Button text="CheckHealth" layoutX="320" layoutY="35" onAction="#checkHealth" prefWidth="90"/>
47+
<ComboBox fx:id="CH_level" prefWidth="90" layoutX="320" layoutY="60" promptText="level" editable="true"/>
48+
<Button text="DirectIO" layoutX="420" layoutY="35" onAction="#directIO" prefWidth="140"/>
49+
<TextField fx:id="DIO_command" prefWidth="70" layoutX="420" layoutY="60" promptText="command"/>
50+
<TextField fx:id="DIO_data" prefWidth="70" layoutX="490" layoutY="60" promptText="data"/>
51+
<TextField fx:id="DIO_obj" prefWidth="140" layoutX="420" layoutY="85" promptText="obj"/>
52+
<Button text="ClearInput" layoutY="90" onAction="#clearInput" prefWidth="70"/>
53+
<Button text="ClearInputProperties" layoutX="80" layoutY="90" onAction="#clearInputProperties" prefWidth="120"/>
54+
<Label fx:id="PromptLabel" text="Display:" layoutX="210" layoutY="75"/>
55+
<ComboBox fx:id="Prompt" layoutX="210" layoutY="90" promptText="Prompt" prefWidth="120" editable="true" onAction="#setPrompt"/>
56+
<ComboBox fx:id="PromptLanguage" promptText="Lang" prefWidth="80" layoutX="330" layoutY="90" editable="true" onAction="#setPromptLanguage"/>
57+
<Label fx:id="MethodActive" layoutY="530"/>
58+
<TabPane layoutY="116" prefWidth="695" prefHeight="424" tabClosingPolicy="UNAVAILABLE">
59+
<Tab text="Specific Properties And Methods">
60+
<AnchorPane prefHeight="409" prefWidth="695">
61+
<Label text="MaximumPINLength: " layoutY="5" prefWidth="110" alignment="CENTER_RIGHT"/>
62+
<TextField fx:id="MaximumPINLength" layoutX="110" prefWidth="40"/>
63+
<Label text="MinimumPINLength: " layoutY="5" layoutX="150" prefWidth="110" alignment="CENTER_RIGHT"/>
64+
<TextField fx:id="MinimumPINLength" layoutX="260" prefWidth="40"/>
65+
<Label text="EncryptedPIN: " layoutY="5" layoutX="300" prefWidth="80" alignment="CENTER_RIGHT"/>
66+
<TextField fx:id="EncryptedPIN" layoutX="380" prefWidth="80"/>
67+
<Label text="AdditionalSecurityInformation: " layoutY="5" layoutX="455" prefWidth="160" alignment="CENTER_RIGHT"/>
68+
<TextField fx:id="AdditionalSecurityInformation" layoutX="615" prefWidth="80"/>
69+
<Label text="AccountNumber: " layoutY="30" prefWidth="90" alignment="CENTER_RIGHT"/>
70+
<TextField fx:id="AccountNumber" layoutX="90" layoutY="25" prefWidth="145"/>
71+
<Label text="Amount: " layoutX="250" layoutY="30" prefWidth="60" alignment="CENTER_RIGHT"/>
72+
<TextField fx:id="Amount" layoutX="310" layoutY="25" prefWidth="95" alignment="CENTER_RIGHT"/>
73+
<Label text="Byte Array Conversion: " layoutX="415" layoutY="30" prefWidth="120" alignment="CENTER_RIGHT"/>
74+
<ComboBox fx:id="ByteArrayConversion" layoutX="535" layoutY="25" prefWidth="120" onAction="#setByteConversion"/>
75+
<Label text="MerchantID: " layoutX="240" layoutY="55" prefWidth="70" alignment="CENTER_RIGHT"/>
76+
<TextField fx:id="MerchantID" layoutX="310" layoutY="50" prefWidth="155" alignment="CENTER_RIGHT"/>
77+
<Label text="TerminalID: " layoutX="465" layoutY="55" prefWidth="70" alignment="CENTER_RIGHT"/>
78+
<TextField fx:id="TerminalID" layoutX="535" layoutY="50" prefWidth="155" alignment="CENTER_RIGHT"/>
79+
<Label text="TransactionType: " layoutY="55" prefWidth="90" alignment="CENTER_RIGHT"/>
80+
<ComboBox fx:id="TransactionType" layoutX="90" layoutY="50" prefWidth="145" editable="true" onAction="#setTransactionType"/>
81+
<Label text="Track1Data: " layoutY="80" prefWidth="65" alignment="CENTER_RIGHT"/>
82+
<TextField fx:id="Track1Data" layoutX="65" layoutY="75" prefWidth="625"/>
83+
<Label text="Track2Data: " layoutY="105" prefWidth="65" alignment="CENTER_RIGHT"/>
84+
<TextField fx:id="Track2Data" layoutX="65" layoutY="100" prefWidth="625"/>
85+
<Label text="Track3Data: " layoutY="130" prefWidth="65" alignment="CENTER_RIGHT"/>
86+
<TextField fx:id="Track3Data" layoutX="65" layoutY="125" prefWidth="625"/>
87+
<Label text="Track4Data: " layoutY="155" prefWidth="65" alignment="CENTER_RIGHT"/>
88+
<TextField fx:id="Track4Data" layoutX="65" layoutY="150" prefWidth="625"/>
89+
<Button text="BeginEFTTransaction" onAction="#beginEFTTransaction" layoutY="180" prefWidth="120"/>
90+
<ComboBox fx:id="BET_system" layoutX="120" layoutY="180" prefWidth="120" promptText="PINPadSystem" editable="true"/>
91+
<TextField fx:id="BET_host" layoutX="240" layoutY="180" prefWidth="120" promptText="transactionHost"/>
92+
<Button text="EnablePINEntry" onAction="#enablePINEntry" layoutY="210" prefWidth="120"/>
93+
<Button text="ComputeMAC" onAction="#computeMAC" layoutY="240" prefWidth="120"/>
94+
<TextField fx:id="CM_inMsg" layoutX="120" layoutY="240" promptText="inMsg" prefWidth="280"/>
95+
<TextField fx:id="CM_outMsg" layoutX="400" layoutY="240" promptText="outMsg" prefWidth="280"/>
96+
<Button text="VerifyMAC" onAction="#verifyMAC" layoutY="270" prefWidth="120"/>
97+
<TextField fx:id="VM_message" layoutX="120" layoutY="270" promptText="message" prefWidth="280"/>
98+
<Button text="UpdateKey" onAction="#updateKey" layoutY="300" prefWidth="120"/>
99+
<TextField fx:id="UK_keyNum" layoutX="120" layoutY="300" promptText="keyNum" prefWidth="60"/>
100+
<TextField fx:id="UK_key" layoutX="180" layoutY="300" promptText="key" prefWidth="220"/>
101+
<Button text="EndEFTTransaction" onAction="#endEFTTransaction" layoutY="330" prefWidth="120"/>
102+
<ComboBox fx:id="EET_completionCode" layoutX="120" layoutY="330" prefWidth="130" promptText="completionCode" editable="true"/>
103+
</AnchorPane>
104+
</Tab>
105+
<Tab text="Maintenance Methods">
106+
<AnchorPane prefHeight="409" prefWidth="695">
107+
<Button onAction="#compareFirmwareVersion" layoutY="5" text="CompareFirmwareVersion" prefWidth="155"/>
108+
<TextField fx:id="CFV_firmwareFileName" layoutY="30" prefWidth="130" promptText="firmwareFileName"/>
109+
<Button styleClass="FileButton" onAction="#browseCFVName" layoutX="130" layoutY="30" text="" prefWidth="25"/>
110+
<TextField fx:id="CFV_result" layoutY="55" prefWidth="155" promptText="result" disable="true"/>
111+
<Button onAction="#updateFirmware" layoutX="165" layoutY="5" text="UpdateFirmware" prefWidth="155"/>
112+
<TextField fx:id="UF_firmwareFileName" layoutX="165" layoutY="30" prefWidth="130" promptText="firmwareFileName"/>
113+
<Button styleClass="FileButton" onAction="#browseUFName" layoutX="295" layoutY="30" text="" prefWidth="25"/>
114+
<Button onAction="#resetStatistics" layoutX="330" layoutY="5" text="ResetStatistics" prefWidth="110"/>
115+
<Button onAction="#retrieveStatistics" layoutX="450" layoutY="5" text="RetrieveStatistics" prefWidth="110"/>
116+
<Button onAction="#updateStatistics" layoutX="570" layoutY="5" text="UpdateStatistics" prefWidth="110"/>
117+
<TextArea fx:id="_statisticsBuffer" layoutX="330" layoutY="30" prefWidth="350" prefHeight="75" promptText="statisticsBuffer"/>
118+
</AnchorPane>
119+
</Tab>
120+
</TabPane>
121+
<Label text="Events" layoutY="121" layoutX="700" prefWidth="280" underline="true" alignment="CENTER"/>
122+
<TextArea fx:id="EventOutput" layoutX="700" layoutY="146" prefWidth="280" prefHeight="389"/>
123+
</AnchorPane>

0 commit comments

Comments
 (0)