304 lines
13 KiB
Java
304 lines
13 KiB
Java
package Web;
|
|
|
|
import Other.SomeCodes;
|
|
import com.corundumstudio.socketio.Configuration;
|
|
import com.corundumstudio.socketio.SocketIOClient;
|
|
import com.corundumstudio.socketio.SocketIOServer;
|
|
import com.corundumstudio.socketio.listener.ConnectListener;
|
|
import com.corundumstudio.socketio.listener.DisconnectListener;
|
|
import io.javalin.Javalin;
|
|
import io.javalin.http.UploadedFile;
|
|
import io.javalin.util.FileUtil;
|
|
import io.javalin.util.JavalinException;
|
|
import io.javalin.websocket.*;
|
|
import lombok.Getter;
|
|
import lombok.Setter;
|
|
import org.tinylog.Logger;
|
|
|
|
import java.util.*;
|
|
import java.util.concurrent.ConcurrentHashMap;
|
|
|
|
import static Other.SomeCodes.*;
|
|
import static io.javalin.apibuilder.ApiBuilder.*;
|
|
|
|
|
|
@SuppressWarnings({"unused"})
|
|
public class WebServer {
|
|
private @Getter @Setter String webusername;
|
|
private @Getter @Setter String webpassword;
|
|
private final Javalin app;
|
|
private final Set<WsContext> connectedWebsocketClients = ConcurrentHashMap.newKeySet();
|
|
private final SocketIOServer socketServer;
|
|
private final Configuration socketConfig;
|
|
private final HashMap<String, SocketIOClient> socketIOClients = new HashMap<>();
|
|
|
|
public WebServer(WebsocketEvent event, String webusername, String webpassword){
|
|
this.webusername = webusername;
|
|
this.webpassword = webpassword;
|
|
app = Javalin.create(config -> {
|
|
config.staticFiles.add("/html");
|
|
config.router.apiBuilder(()-> path("setting", () ->{
|
|
get(ctx -> ctx.json(SettingInfo.getInstance()));
|
|
path("audiofile",()-> post(ctx -> {
|
|
Logger.info("api /setting/audiofile");
|
|
String audiofile1 = ctx.formParam("preset1");
|
|
String audiofile2 = ctx.formParam("preset2");
|
|
String audiofile3 = ctx.formParam("preset3");
|
|
String audiofile4 = ctx.formParam("preset4");
|
|
String audiofile5 = ctx.formParam("preset5");
|
|
Logger.info("audiofile1: {}", audiofile1);
|
|
Logger.info("audiofile2: {}", audiofile2);
|
|
Logger.info("audiofile3: {}", audiofile3);
|
|
Logger.info("audiofile4: {}", audiofile4);
|
|
Logger.info("audiofile5: {}", audiofile5);
|
|
|
|
Properties prop = SomeCodes.LoadProperties("config.properties");
|
|
prop.setProperty("AudioFile01", audiofile1!=null?audiofile1:"");
|
|
prop.setProperty("AudioFile02", audiofile2!=null?audiofile2:"");
|
|
prop.setProperty("AudioFile03", audiofile3!=null?audiofile3:"");
|
|
prop.setProperty("AudioFile04", audiofile4!=null?audiofile4:"");
|
|
prop.setProperty("AudioFile05", audiofile5!=null?audiofile5:"");
|
|
if (SaveProperties(prop, "config.properties")){
|
|
Logger.info("audiofile saved");
|
|
ctx.status(200);
|
|
} else {
|
|
Logger.error("Failed to save audiofile");
|
|
ctx.status(400);
|
|
ctx.result("Failed to save audiofile");
|
|
}
|
|
}));
|
|
path("uploadaudiofile", ()-> post(ctx -> {
|
|
List<UploadedFile> uploadedFileList = ctx.uploadedFiles();
|
|
int size = uploadedFileList.size();
|
|
if (size>0){
|
|
uploadedFileList.forEach(ff ->{
|
|
String targetsave = audioPath.resolve(ff.filename()).toString();
|
|
FileUtil.streamToFile(ff.content(), targetsave);
|
|
Logger.info("Uploaded file: {}", targetsave);
|
|
});
|
|
ctx.status(200);
|
|
ctx.result("UploadedFiles: "+size);
|
|
} else {
|
|
ctx.status(400);
|
|
ctx.result("No file uploaded");
|
|
}
|
|
|
|
|
|
}));
|
|
path("weblogin", ()-> post(ctx -> {
|
|
String username = ctx.formParam("username");
|
|
String password = ctx.formParam("password");
|
|
Logger.info("api /setting/weblogin");
|
|
Logger.info("username: {}", username);
|
|
Logger.info("password: {}", password);
|
|
|
|
Properties prop = SomeCodes.LoadProperties("config.properties");
|
|
prop.setProperty("WebUsername", ValidString(username)?username:"admin");
|
|
prop.setProperty("WebPassword", ValidString(password)?password:"bandara");
|
|
if (SaveProperties(prop, "config.properties")){
|
|
Logger.info("weblogin saved");
|
|
|
|
//ctx.status(200);
|
|
this.webusername = username;
|
|
this.webpassword = password;
|
|
ctx.redirect("/logout");
|
|
} else {
|
|
Logger.error("Failed to save weblogin");
|
|
ctx.status(400);
|
|
ctx.result("Failed to save weblogin");
|
|
}
|
|
}));
|
|
path("camera",()-> post(ctx -> {
|
|
String camera_ip = ctx.formParam("ip");
|
|
String camera_port = ctx.formParam("port");
|
|
String camera_username = ctx.formParam("username");
|
|
String camera_password = ctx.formParam("password");
|
|
Logger.info("api /setting/camera");
|
|
Logger.info("camera_ip: {}", camera_ip);
|
|
Logger.info("camera_port: {}", camera_port);
|
|
Logger.info("camera_username: {}", camera_username);
|
|
Logger.info("camera_password: {}", camera_password);
|
|
|
|
Properties prop = SomeCodes.LoadProperties("config.properties");
|
|
prop.setProperty("Camera_ip", ValidString(camera_ip)?camera_ip:"192.168.0.4");
|
|
prop.setProperty("Camera_port", ValidString(camera_port)?camera_port:"80");
|
|
prop.setProperty("Camera_user", ValidString(camera_username)?camera_username:"root");
|
|
prop.setProperty("Camera_password", ValidString(camera_password)?camera_password:"password");
|
|
if (SaveProperties(prop, "config.properties")){
|
|
Logger.info("IP camera setting saved");
|
|
ctx.status(200);
|
|
if (event!=null) event.NewCameraConfiguration();
|
|
} else {
|
|
Logger.error("Failed to save IP camera setting");
|
|
ctx.status(400);
|
|
ctx.result("Failed to save IP camera setting");
|
|
}
|
|
}));
|
|
|
|
}));
|
|
});
|
|
|
|
app.get("/", ctx-> {
|
|
if (ctx.sessionAttribute("username")==null) {
|
|
// belum login
|
|
ctx.redirect("/login.html");
|
|
} else if (Objects.equals(ctx.sessionAttribute("username"), this.webusername)){
|
|
// sudah login
|
|
ctx.redirect("/index.html");
|
|
} else {
|
|
// sudah login tapi bukan username yang benar
|
|
ctx.redirect("/login.html");
|
|
}
|
|
});
|
|
|
|
app.before("/index.html", ctx ->{
|
|
if (ctx.sessionAttribute("username")==null){
|
|
ctx.redirect("/login.html");
|
|
}
|
|
});
|
|
|
|
app.before("/setting.html", ctx ->{
|
|
if (ctx.sessionAttribute("username")==null){
|
|
ctx.redirect("/login.html");
|
|
}
|
|
});
|
|
|
|
app.post("/login", ctx ->{
|
|
String username = ctx.formParam("username");
|
|
String password = ctx.formParam("password");
|
|
if (Objects.equals(username, this.webusername) && Objects.equals(password, this.webpassword)){
|
|
ctx.sessionAttribute("username", username);
|
|
ctx.redirect("/index.html");
|
|
} else {
|
|
ctx.status(400);
|
|
ctx.redirect("/login.html");
|
|
}
|
|
});
|
|
|
|
app.get("/logout", ctx ->{
|
|
ctx.sessionAttribute("username", null);
|
|
ctx.redirect("/login.html");
|
|
});
|
|
|
|
/*
|
|
WebSocket Communication
|
|
This is temporary, later must choose either WebSocket or SocketIO
|
|
*/
|
|
app.ws("/ws", ws -> {
|
|
ws.onConnect(connectws);
|
|
ws.onClose(closews);
|
|
ws.onMessage(ctx -> {
|
|
try{
|
|
//Logger.info("WebSocket message {}", ctx.message());
|
|
WebsocketCommand command = ctx.messageAsClass(WebsocketCommand.class);
|
|
if (event!=null) {
|
|
WebsocketReply reply = event.onWebsocketCommand(command);
|
|
if (reply!=null) ctx.sendAsClass(reply, WebsocketReply.class);
|
|
//if (reply!=null) SendtoAll(reply);
|
|
}
|
|
} catch (Exception e){
|
|
Logger.error("Failed to parse WebSocketCommand message: {}", e.getMessage());
|
|
ctx.closeSession();
|
|
connectedWebsocketClients.remove(ctx);
|
|
}
|
|
});
|
|
|
|
});
|
|
|
|
/*
|
|
SocketIO Communication
|
|
This is temporary, later must choose either WebSocket or SocketIO
|
|
*/
|
|
socketConfig = new Configuration();
|
|
socketConfig.setHostname("0.0.0.0");
|
|
socketConfig.setPort(3001);
|
|
|
|
socketServer = new SocketIOServer(socketConfig);
|
|
socketServer.addConnectListener(connectListener);
|
|
socketServer.addDisconnectListener(disconnectListener);
|
|
|
|
socketServer.addNamespace("/socketio").addEventListener("message", String.class, (client, data, ackSender) -> {
|
|
//Logger.info("SocketIO message from namespace /socketio from {}: {}", client.getRemoteAddress(), data);
|
|
WebsocketCommand command = gson.fromJson(data, WebsocketCommand.class);
|
|
if (event!=null) {
|
|
WebsocketReply reply = event.onWebsocketCommand(command);
|
|
if (reply!=null) client.sendEvent("message", gson.toJson(reply));
|
|
}
|
|
});
|
|
|
|
|
|
}
|
|
|
|
/**
|
|
* Send Object message to all connected websocket clients
|
|
* @param obj Object to send
|
|
*/
|
|
public void SendtoAll(Object obj){
|
|
|
|
connectedWebsocketClients
|
|
.stream()
|
|
.filter(ws -> ws.session.isOpen())
|
|
.forEach(ws -> ws.send(obj));
|
|
socketIOClients.forEach((key, client) -> client.sendEvent("message", gson.toJson(obj)));
|
|
}
|
|
|
|
/**
|
|
* Start the web server
|
|
* @param localip Local IP address to bind
|
|
* @param port Port to bind
|
|
*/
|
|
public void Start(String localip, int port){
|
|
try{
|
|
app.start(localip, port);
|
|
Logger.info("Web server started at {}:{}", localip, port);
|
|
socketServer.start();
|
|
Logger.info("SocketIO server started at {}:{}", socketConfig.getHostname(), socketConfig.getPort());
|
|
} catch (JavalinException e){
|
|
Logger.error("Web server failed to start: {}", e.getMessage());
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Stop the web server
|
|
*/
|
|
public void Stop(){
|
|
try{
|
|
connectedWebsocketClients.forEach(WsContext::closeSession);
|
|
connectedWebsocketClients.clear();
|
|
app.stop();
|
|
Logger.info("Web server stopped");
|
|
socketIOClients.forEach((key, client) -> client.disconnect());
|
|
socketIOClients.clear();
|
|
socketServer.stop();
|
|
Logger.info("SocketIO server stopped");
|
|
} catch (JavalinException e){
|
|
Logger.error("Web server failed to stop: {}", e.getMessage());
|
|
}
|
|
}
|
|
|
|
WsConnectHandler connectws = ws ->{
|
|
Logger.info("WebSocket connected from {}", ws.sessionId());
|
|
//ws.headerMap().forEach((key, value) -> Logger.info("HeaderMap {}: {}", key, value));
|
|
connectedWebsocketClients.add(ws);
|
|
};
|
|
|
|
WsCloseHandler closews = ws ->{
|
|
Logger.info("WebSocket closed from {}, code {}, reason {}", ws.sessionId(), ws.status(), ws.reason());
|
|
connectedWebsocketClients.remove(ws);
|
|
};
|
|
|
|
ConnectListener connectListener = client -> {
|
|
Logger.info("SocketIO connected, id {} from {}", client.getSessionId(), client.getRemoteAddress());
|
|
socketIOClients.put(client.getSessionId().toString(), client);
|
|
};
|
|
|
|
DisconnectListener disconnectListener = client -> {
|
|
Logger.info("SocketIO disconnected, id {} from {}", client.getSessionId(), client.getRemoteAddress());
|
|
socketIOClients.remove(client.getSessionId().toString());
|
|
};
|
|
|
|
|
|
|
|
|
|
}
|