diff --git a/.idea/compiler.xml b/.idea/compiler.xml
new file mode 100644
index 0000000..a1757ae
--- /dev/null
+++ b/.idea/compiler.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/libraries/slf4j_simple.xml b/.idea/libraries/slf4j_simple.xml
new file mode 100644
index 0000000..16c12c5
--- /dev/null
+++ b/.idea/libraries/slf4j_simple.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Properties/simplelogger.properties b/Properties/simplelogger.properties
new file mode 100644
index 0000000..d1de872
--- /dev/null
+++ b/Properties/simplelogger.properties
@@ -0,0 +1,34 @@
+# SLF4J's SimpleLogger configuration file
+# Simple implementation of Logger that sends all enabled log messages, for all defined loggers, to System.err.
+
+# Default logging detail level for all instances of SimpleLogger.
+# Must be one of ("trace", "debug", "info", "warn", or "error").
+# If not specified, defaults to "info".
+org.slf4j.simpleLogger.defaultLogLevel=warn
+
+# Logging detail level for a SimpleLogger instance named "xxxxx".
+# Must be one of ("trace", "debug", "info", "warn", or "error").
+# If not specified, the default logging detail level is used.
+#org.slf4j.simpleLogger.log.xxxxx=
+
+# Set to true if you want the current date and time to be included in output messages.
+# Default is false, and will output the number of milliseconds elapsed since startup.
+#org.slf4j.simpleLogger.showDateTime=false
+
+# The date and time format to be used in the output messages.
+# The pattern describing the date and time format is the same that is used in java.text.SimpleDateFormat.
+# If the format is not specified or is invalid, the default format is used.
+# The default format is yyyy-MM-dd HH:mm:ss:SSS Z.
+#org.slf4j.simpleLogger.dateTimeFormat=yyyy-MM-dd HH:mm:ss:SSS Z
+
+# Set to true if you want to output the current thread name.
+# Defaults to true.
+#org.slf4j.simpleLogger.showThreadName=true
+
+# Set to true if you want the Logger instance name to be included in output messages.
+# Defaults to true.
+#org.slf4j.simpleLogger.showLogName=true
+
+# Set to true if you want the last component of the name to be included in output messages.
+# Defaults to false.
+#org.slf4j.simpleLogger.showShortLogName=false
\ No newline at end of file
diff --git a/Properties/tinylog.properties b/Properties/tinylog.properties
new file mode 100644
index 0000000..c4de797
--- /dev/null
+++ b/Properties/tinylog.properties
@@ -0,0 +1,9 @@
+//writer = rolling file
+writer=console
+writer.file=logs/{date:yyyy-MM-dd}.log
+writer.format={date:yyyy-MM-dd HH:mm:ss} {level}: {class}.{method}() {message}
+writer.policies=daily
+writer.buffered=true
+writer.charset=UTF-8
+writer.level=info
+writer.append=true
\ No newline at end of file
diff --git a/ProtegeToAASMini.iml b/ProtegeToAASMini.iml
index 237d7ef..20fcc54 100644
--- a/ProtegeToAASMini.iml
+++ b/ProtegeToAASMini.iml
@@ -5,6 +5,7 @@
+
@@ -21,5 +22,6 @@
+
\ No newline at end of file
diff --git a/src/AASMini/AASMini.java b/src/AASMini/AASMini.java
index 2aa39a5..49cd18c 100644
--- a/src/AASMini/AASMini.java
+++ b/src/AASMini/AASMini.java
@@ -4,12 +4,15 @@ import org.pmw.tinylog.Logger;
import java.net.InetAddress;
import java.net.Socket;
+import java.nio.charset.StandardCharsets;
+import java.util.Arrays;
-@SuppressWarnings("unused")
+
+@SuppressWarnings({"FieldCanBeLocal", "UnusedReturnValue"})
public class AASMini {
private final String targetIP;
private final int targetPort;
- private final int msgId = 15;
+ private final int msgId = 1;
private final String zones = "Zone_1,Zone_2,Zone_3,Zone_4";
private Socket socket;
@@ -70,21 +73,35 @@ public class AASMini {
socket = null;
}
- //TODO protocol untuk kirim data ke AAS Mini
- private void SendPlatNoToAAS(String platNo){
+ private String ConvertToString(byte[] data){
+ StringBuilder sb = new StringBuilder();
+ for (byte b : data){
+ if (b>0x1F && b<0x7F)
+ sb.append((char)b);
+ else break;
+
+ }
+ return sb.toString();
+ }
+
+ public void SendPlatNoToAAS(String platNo){
String protocol = "BROADCAST;"+msgId+";IND;$PLATNOMOR$="+platNo+";"+zones;
byte[] data = protocol.getBytes();
byte[] rplyData = SendAndReceive(data);
- String rplyInStr = rplyData.toString();
- String[] rply = rplyInStr.split(";");
- if (rply.length ==2){
- if (rply[0].equals("BROADCAST")){
- if (rply[1].equals("OK")){
- System.out.println("Success sending data to AAS!");
- }else System.out.println("Failed sending data to AAS!");
- }else System.out.println("Wrong format answer!");
- }else System.out.println("Wrong size answer");
+ if (rplyData!=null && rplyData.length>0){
+ String rplyInStr = ConvertToString(rplyData);
+ Logger.info("Response from AAS : {}", rplyInStr);
+ String[] rply = rplyInStr.split(";");
+ if (rply.length ==2){
+ if (rply[0].equals("BROADCAST")){
+ if (rply[1].equals("OK")){
+ Logger.info("Success sending data to AAS!");
+ }else Logger.info("Failed sending data to AAS!");
+ }else Logger.info("Wrong format answer!");
+ }else Logger.info("Wrong size answer");
+ } else Logger.info("SendAndReceive return null");
+
}
@@ -101,9 +118,7 @@ public class AASMini {
byte[] buffer = new byte[1024];
int read = socket.getInputStream().read(buffer);
if (read>0){
- byte[] result = new byte[read];
- System.arraycopy(buffer, 0, result, 0, read);
- return result;
+ return buffer;
}
} catch (Exception e){
Logger.error("Failed to send data to {}:{}, Error : {}", targetIP, targetPort, e.getMessage());
@@ -113,10 +128,10 @@ public class AASMini {
return null;
}
- /**
+ /*
* Send data to AAS Mini
* @param data Data to be sent
- */
+
private void SendData(byte[] data){
if (IsConnected()){
if (data!=null && data.length>0){
@@ -128,4 +143,5 @@ public class AASMini {
}
}
}
+ */
}
diff --git a/src/Main.java b/src/Main.java
index f586efa..dd7a779 100644
--- a/src/Main.java
+++ b/src/Main.java
@@ -4,34 +4,35 @@ import Web.WebResponse;
import Web.WebServer;
import org.pmw.tinylog.Logger;
+import java.io.File;
+import java.io.InputStream;
+import java.nio.file.Files;
+
public class Main {
private static AASMini aas;
private static ProtegeGX protegeGX;
private static WebServer web;
- private static String aasIP = "192.168.10.10";
+ private static String aasIP = "localhost";
private static int aasPort = 5000;
private static int webPort = 8080;
+ private final static String currentDirectory = System.getProperty("user.dir");
+
public static void main(String[] args) {
+ ExtractFile("tinylog.properties");
+ ExtractFile("simplelogger.properties");
GetArguments(args);
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
- System.out.println("Shutting down...");
- if (aas!=null) aas.Disconnect();
+ Logger.info("Shutting down...");
if (protegeGX!=null) protegeGX.Disconnect();
if (web!=null) web.Stop();
}));
- System.out.println("Protege to AAS Mini Connector");
+ Logger.info("Protege to AAS Mini Connector");
- protegeGX = new ProtegeGX();
- protegeGX.setOnCardRead(data -> {
- Logger.info(data);
- if (aas!=null && aas.IsConnected()){
- // send something to AAS
- }
- });
+ protegeGX = new ProtegeGX(5004);
+ protegeGX.setOnCardRead(data -> SendPlatNomor(data.LastName));
aas = new AASMini(aasIP, aasPort);
- aas.Connect();
web = new WebServer();
web.Start(webPort);
@@ -47,6 +48,37 @@ public class Main {
WebResponse response = new WebResponse();
return response;
});
+
+ Logger.info("Sending dummy to AAS Mini");
+ SendPlatNomor("B2902PFO");
+ }
+
+ private static void SendPlatNomor(String platNomor){
+ if (aas!=null){
+ if (aas.Connect()){
+ aas.SendPlatNoToAAS(platNomor);
+ aas.Disconnect();
+ } else Logger.error("Failed to connect to AAS Mini");
+ } else Logger.error("AAS Mini is not created");
+
+ }
+
+ private static void ExtractFile(String filename){
+ File target = new File(currentDirectory,filename);
+ if (target.isFile()) {
+ Logger.info("File {} already exists", filename);
+ return;
+ }
+
+ try{
+ InputStream in = Main.class.getResourceAsStream("/"+filename);
+ if (in!=null){
+ Files.copy(in, target.toPath());
+ Logger.info("File {} extracted", filename);
+ } else throw new Exception("File not found");
+ } catch (Exception e){
+ Logger.error("Failed to extract file {}, Message : {}", filename, e.getMessage());
+ }
}
private static void GetArguments(String[] args){
diff --git a/src/ProtegeGX/ProtegeData.java b/src/ProtegeGX/ProtegeData.java
index e8e2025..3c8b39e 100644
--- a/src/ProtegeGX/ProtegeData.java
+++ b/src/ProtegeGX/ProtegeData.java
@@ -1,12 +1,43 @@
package ProtegeGX;
+import java.util.regex.Pattern;
+
public class ProtegeData {
- public String ReaderID;
- public String CardID;
- public String Description;
+ public String FirstName;
+ public String LastName;
+ public String CardNumber;
+ public int UserNode;
+ public String DoorName;
+ public int DoorNode;
+ public String FieldTime;
+ public String LoggedTime;
@Override
public String toString(){
- return "ReaderID = " + ReaderID + ", CardID = " + CardID + ", Description = " + Description;
+ return String.format("FirstName: %s\nLastName: %s\nCardNumber: %s\nUserNode: %d\nDoorName: %s\nDoorNode: %d\nFieldTime: %s\nLoggedTime: %s", FirstName, LastName, CardNumber, UserNode, DoorName, DoorNode, FieldTime, LoggedTime);
+ }
+
+ /**
+ * create EventData object from string data using Regex
+ * @param data string data
+ * @return EventData object if valid, or null if invalid
+ */
+ public static ProtegeData Parse(String data){
+ final String regex = "User (\\w*) (\\w*) \\(([:0-9]*)\\) \\(UN(\\d+)\\).*?To (.*?) \\(DR(\\d+)\\).*?.*?(.*?).*?(.*?)";
+ final Pattern pattern = Pattern.compile(regex, Pattern.DOTALL);
+ final java.util.regex.Matcher matcher = pattern.matcher(data);
+ if (matcher.find()){
+ ProtegeData event = new ProtegeData();
+ event.FirstName = matcher.group(1);
+ event.LastName = matcher.group(2);
+ event.CardNumber = matcher.group(3);
+ event.UserNode = Integer.parseInt(matcher.group(4));
+ event.DoorName = matcher.group(5);
+ event.DoorNode = Integer.parseInt(matcher.group(6));
+ event.FieldTime = matcher.group(7);
+ event.LoggedTime = matcher.group(8);
+ return event;
+ }
+ return null;
}
}
diff --git a/src/ProtegeGX/ProtegeGX.java b/src/ProtegeGX/ProtegeGX.java
index 748ab15..cc4f402 100644
--- a/src/ProtegeGX/ProtegeGX.java
+++ b/src/ProtegeGX/ProtegeGX.java
@@ -1,20 +1,87 @@
package ProtegeGX;
+import lombok.Getter;
import lombok.Setter;
+import org.pmw.tinylog.Logger;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.ServerSocket;
+import java.net.Socket;
import java.util.function.Consumer;
-@SuppressWarnings("unused")
public class ProtegeGX {
@Setter private Consumer onCardRead;
+ private ServerSocket serverSocket;
+ @Getter private boolean running ;
- private void updateCardRead(String data) {
- if (onCardRead != null) {
- ProtegeData protegeData = new ProtegeData();
- onCardRead.accept(protegeData);
+ private void UpdateCardData(String data){
+ if (data!=null && !data.isEmpty()){
+ ProtegeData cardData = ProtegeData.Parse(data);
+ if (cardData!=null){
+ Logger.info("Card data: "+cardData);
+ if (onCardRead!=null){
+ onCardRead.accept(cardData);
+ }
+ }
+ }
+
+ }
+
+
+
+ public ProtegeGX(int localport) {
+ running = false;
+ try{
+ serverSocket = new ServerSocket(localport);
+ running = true;
+ Logger.info("ProtegeGX server started on port "+localport);
+ // Thread untuk serverSocket accept client
+ new Thread(()->{
+ while(running){
+ try {
+ Socket client = serverSocket.accept();
+ // Thread untuk komunikasi dengan client
+ new Thread(()->{
+ try {
+ Logger.info("Client connected: "+client.getInetAddress().getHostAddress());
+ InputStream in = client.getInputStream();
+ while(running){
+ byte[] buffer = new byte[1024];
+ int bytesRead = in.read(buffer);
+ if (bytesRead>0){
+ String data = new String(buffer, 0, bytesRead);
+ //Logger.info("Data received: "+data);
+ UpdateCardData(data);
+ }
+ }
+ client.close();
+ Logger.info("Client disconnected: "+client.getInetAddress().getHostAddress());
+ } catch (IOException e) {
+ Logger.error("Failed to read data from client: "+e.getMessage());
+ }
+
+ }).start();
+ } catch (IOException e) {
+ Logger.error("Failed to accept client connection: "+e.getMessage());
+ }
+ }
+ }).start();
+ } catch (Exception e){
+ Logger.error("Failed to create server socket: "+e.getMessage());
}
}
+
public void Disconnect() {
- throw new UnsupportedOperationException("Not supported yet.");
+ running = false;
+ if (serverSocket!=null){
+ try{
+ serverSocket.close();
+ Logger.info("ProtegeGX server stopped");
+ } catch (Exception e){
+ Logger.error("Failed to close server socket: "+e.getMessage());
+ }
+ }
+ serverSocket = null;
}
}
diff --git a/src/Web/WebServer.java b/src/Web/WebServer.java
index 2091e71..4b1132c 100644
--- a/src/Web/WebServer.java
+++ b/src/Web/WebServer.java
@@ -2,8 +2,11 @@ package Web;
import com.google.gson.Gson;
import io.javalin.Javalin;
+import io.javalin.core.util.JavalinLogger;
import io.javalin.http.staticfiles.Location;
+import io.javalin.jetty.JettyUtil;
import lombok.Setter;
+import org.eclipse.jetty.util.log.Log;
import java.util.function.Function;
@@ -31,8 +34,10 @@ public class WebServer {
Javalin app;
public WebServer(){
+ JettyUtil.disableJettyLogger();
+ JavalinLogger.enabled = false;
app = Javalin.create(config -> {
- config.addStaticFiles("/Web", Location.EXTERNAL);
+ config.addStaticFiles("/Web", Location.CLASSPATH);
});
app.get("/", ctx -> ctx.result("Hello World"));
app.get("/aasmini", ctx -> ctx.result("AAS Mini API"));