running good

This commit is contained in:
2024-12-14 15:23:54 +07:00
parent ec427a70b8
commit 68991fe061
10 changed files with 256 additions and 41 deletions

8
.idea/compiler.xml generated Normal file
View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CompilerConfiguration">
<annotationProcessing>
<profile default="true" name="Default" enabled="true" />
</annotationProcessing>
</component>
</project>

11
.idea/libraries/slf4j_simple.xml generated Normal file
View File

@@ -0,0 +1,11 @@
<component name="libraryTable">
<library name="slf4j.simple" type="repository">
<properties maven-id="org.slf4j:slf4j-simple:1.8.0-beta4" />
<CLASSES>
<root url="jar://$MAVEN_REPOSITORY$/org/slf4j/slf4j-simple/1.8.0-beta4/slf4j-simple-1.8.0-beta4.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/org/slf4j/slf4j-api/1.8.0-beta4/slf4j-api-1.8.0-beta4.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</component>

View File

@@ -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

View File

@@ -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

View File

@@ -5,6 +5,7 @@
<content url="file://$MODULE_DIR$"> <content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/Web" isTestSource="false" /> <sourceFolder url="file://$MODULE_DIR$/Web" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" /> <sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/Properties" isTestSource="false" />
</content> </content>
<orderEntry type="inheritedJdk" /> <orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" /> <orderEntry type="sourceFolder" forTests="false" />
@@ -21,5 +22,6 @@
<orderEntry type="library" name="io.javalin" level="project" /> <orderEntry type="library" name="io.javalin" level="project" />
<orderEntry type="library" name="projectlombok.lombok" level="project" /> <orderEntry type="library" name="projectlombok.lombok" level="project" />
<orderEntry type="library" name="google.code.gson" level="project" /> <orderEntry type="library" name="google.code.gson" level="project" />
<orderEntry type="library" name="slf4j.simple" level="project" />
</component> </component>
</module> </module>

View File

@@ -4,12 +4,15 @@ import org.pmw.tinylog.Logger;
import java.net.InetAddress; import java.net.InetAddress;
import java.net.Socket; import java.net.Socket;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
@SuppressWarnings("unused")
@SuppressWarnings({"FieldCanBeLocal", "UnusedReturnValue"})
public class AASMini { public class AASMini {
private final String targetIP; private final String targetIP;
private final int targetPort; 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 final String zones = "Zone_1,Zone_2,Zone_3,Zone_4";
private Socket socket; private Socket socket;
@@ -70,21 +73,35 @@ public class AASMini {
socket = null; socket = null;
} }
//TODO protocol untuk kirim data ke AAS Mini private String ConvertToString(byte[] data){
private void SendPlatNoToAAS(String platNo){ 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; String protocol = "BROADCAST;"+msgId+";IND;$PLATNOMOR$="+platNo+";"+zones;
byte[] data = protocol.getBytes(); byte[] data = protocol.getBytes();
byte[] rplyData = SendAndReceive(data); byte[] rplyData = SendAndReceive(data);
String rplyInStr = rplyData.toString(); if (rplyData!=null && rplyData.length>0){
String[] rply = rplyInStr.split(";"); String rplyInStr = ConvertToString(rplyData);
if (rply.length ==2){ Logger.info("Response from AAS : {}", rplyInStr);
if (rply[0].equals("BROADCAST")){ String[] rply = rplyInStr.split(";");
if (rply[1].equals("OK")){ if (rply.length ==2){
System.out.println("Success sending data to AAS!"); if (rply[0].equals("BROADCAST")){
}else System.out.println("Failed sending data to AAS!"); if (rply[1].equals("OK")){
}else System.out.println("Wrong format answer!"); Logger.info("Success sending data to AAS!");
}else System.out.println("Wrong size answer"); }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]; byte[] buffer = new byte[1024];
int read = socket.getInputStream().read(buffer); int read = socket.getInputStream().read(buffer);
if (read>0){ if (read>0){
byte[] result = new byte[read]; return buffer;
System.arraycopy(buffer, 0, result, 0, read);
return result;
} }
} catch (Exception e){ } catch (Exception e){
Logger.error("Failed to send data to {}:{}, Error : {}", targetIP, targetPort, e.getMessage()); Logger.error("Failed to send data to {}:{}, Error : {}", targetIP, targetPort, e.getMessage());
@@ -113,10 +128,10 @@ public class AASMini {
return null; return null;
} }
/** /*
* Send data to AAS Mini * Send data to AAS Mini
* @param data Data to be sent * @param data Data to be sent
*/
private void SendData(byte[] data){ private void SendData(byte[] data){
if (IsConnected()){ if (IsConnected()){
if (data!=null && data.length>0){ if (data!=null && data.length>0){
@@ -128,4 +143,5 @@ public class AASMini {
} }
} }
} }
*/
} }

View File

@@ -4,34 +4,35 @@ import Web.WebResponse;
import Web.WebServer; import Web.WebServer;
import org.pmw.tinylog.Logger; import org.pmw.tinylog.Logger;
import java.io.File;
import java.io.InputStream;
import java.nio.file.Files;
public class Main { public class Main {
private static AASMini aas; private static AASMini aas;
private static ProtegeGX protegeGX; private static ProtegeGX protegeGX;
private static WebServer web; 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 aasPort = 5000;
private static int webPort = 8080; private static int webPort = 8080;
private final static String currentDirectory = System.getProperty("user.dir");
public static void main(String[] args) { public static void main(String[] args) {
ExtractFile("tinylog.properties");
ExtractFile("simplelogger.properties");
GetArguments(args); GetArguments(args);
Runtime.getRuntime().addShutdownHook(new Thread(() -> { Runtime.getRuntime().addShutdownHook(new Thread(() -> {
System.out.println("Shutting down..."); Logger.info("Shutting down...");
if (aas!=null) aas.Disconnect();
if (protegeGX!=null) protegeGX.Disconnect(); if (protegeGX!=null) protegeGX.Disconnect();
if (web!=null) web.Stop(); if (web!=null) web.Stop();
})); }));
System.out.println("Protege to AAS Mini Connector"); Logger.info("Protege to AAS Mini Connector");
protegeGX = new ProtegeGX(); protegeGX = new ProtegeGX(5004);
protegeGX.setOnCardRead(data -> { protegeGX.setOnCardRead(data -> SendPlatNomor(data.LastName));
Logger.info(data);
if (aas!=null && aas.IsConnected()){
// send something to AAS
}
});
aas = new AASMini(aasIP, aasPort); aas = new AASMini(aasIP, aasPort);
aas.Connect();
web = new WebServer(); web = new WebServer();
web.Start(webPort); web.Start(webPort);
@@ -47,6 +48,37 @@ public class Main {
WebResponse response = new WebResponse(); WebResponse response = new WebResponse();
return response; 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){ private static void GetArguments(String[] args){

View File

@@ -1,12 +1,43 @@
package ProtegeGX; package ProtegeGX;
import java.util.regex.Pattern;
public class ProtegeData { public class ProtegeData {
public String ReaderID; public String FirstName;
public String CardID; public String LastName;
public String Description; public String CardNumber;
public int UserNode;
public String DoorName;
public int DoorNode;
public String FieldTime;
public String LoggedTime;
@Override @Override
public String toString(){ 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 = "<Description>User (\\w*) (\\w*) \\(([:0-9]*)\\) \\(UN(\\d+)\\).*?To (.*?) \\(DR(\\d+)\\).*?</Description>.*?<FieldTime>(.*?)</FieldTime>.*?<LoggedTime>(.*?)</LoggedTime>";
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;
} }
} }

View File

@@ -1,20 +1,87 @@
package ProtegeGX; package ProtegeGX;
import lombok.Getter;
import lombok.Setter; 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; import java.util.function.Consumer;
@SuppressWarnings("unused")
public class ProtegeGX { public class ProtegeGX {
@Setter private Consumer<ProtegeData> onCardRead; @Setter private Consumer<ProtegeData> onCardRead;
private ServerSocket serverSocket;
@Getter private boolean running ;
private void updateCardRead(String data) { private void UpdateCardData(String data){
if (onCardRead != null) { if (data!=null && !data.isEmpty()){
ProtegeData protegeData = new ProtegeData(); ProtegeData cardData = ProtegeData.Parse(data);
onCardRead.accept(protegeData); 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() { 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;
} }
} }

View File

@@ -2,8 +2,11 @@ package Web;
import com.google.gson.Gson; import com.google.gson.Gson;
import io.javalin.Javalin; import io.javalin.Javalin;
import io.javalin.core.util.JavalinLogger;
import io.javalin.http.staticfiles.Location; import io.javalin.http.staticfiles.Location;
import io.javalin.jetty.JettyUtil;
import lombok.Setter; import lombok.Setter;
import org.eclipse.jetty.util.log.Log;
import java.util.function.Function; import java.util.function.Function;
@@ -31,8 +34,10 @@ public class WebServer {
Javalin app; Javalin app;
public WebServer(){ public WebServer(){
JettyUtil.disableJettyLogger();
JavalinLogger.enabled = false;
app = Javalin.create(config -> { app = Javalin.create(config -> {
config.addStaticFiles("/Web", Location.EXTERNAL); config.addStaticFiles("/Web", Location.CLASSPATH);
}); });
app.get("/", ctx -> ctx.result("Hello World")); app.get("/", ctx -> ctx.result("Hello World"));
app.get("/aasmini", ctx -> ctx.result("AAS Mini API")); app.get("/aasmini", ctx -> ctx.result("AAS Mini API"));