-
-
diff --git a/Html/html/setting.js b/Html/html/setting.js
index 7074c4a..9cefc79 100644
--- a/Html/html/setting.js
+++ b/Html/html/setting.js
@@ -54,7 +54,14 @@ function fill_select(index, values){
*/
let preset = document.getElementById("preset"+index);
preset.innerHTML = "";
+
if (values!=null && values.length>0){
+ // add empty option
+ let option = document.createElement("option");
+ option.value = "";
+ option.innerText = "";
+ preset.appendChild(option);
+
for (let i = 0; i < values.length; i++) {
const element = values[i];
let option = document.createElement("option");
@@ -108,4 +115,91 @@ function showConfirm() {
icon.classList.remove('fa-eye-slash');
icon.classList.add('fa-eye');
}
+}
+
+function save_audio(){
+ let preset1 = $('#preset1').val();
+ let preset2 = $('#preset2').val();
+ let preset3 = $('#preset3').val();
+ let preset4 = $('#preset4').val();
+ let preset5 = $('#preset5').val();
+
+ if (confirm("Are you sure want to change Audio Preset ?")){
+ fetch("/setting/audiofile", {
+ method: "POST",
+ headers: {
+ "Content-Type": "application/x-www-form-urlencoded"
+ },
+ body: new URLSearchParams({preset1: preset1, preset2: preset2, preset3: preset3, preset4: preset4, preset5: preset5})
+ }).then(resp => {
+ if (resp.status === 200) {
+ alert("Success");
+ } else {
+ resp.text().then(text=>alert("Failed to change Audio Preset : "+text));
+ }
+ });
+ }
+}
+
+function save_camera(){
+ let ip = $('#setting_ip').val();
+ let port = $('#setting_port').val();
+ let username = $('#setting_username').val();
+ let password = $('#setting_password').val();
+
+ if (confirm("Are you sure want to change Camera Information ?")){
+ fetch("/setting/camera", {
+ method: "POST",
+ headers: {
+ "Content-Type": "application/x-www-form-urlencoded"
+ },
+ body: new URLSearchParams({ip: ip, port: port, username: username, password: password})
+ }).then(resp => {
+ if (resp.status === 200) {
+ alert("Success");
+ } else {
+ resp.text().then(text => {
+ alert("Failed to change Camera Information : "+text);
+ });
+
+ }
+
+ });
+ }
+}
+
+function save_login(){
+ let username = $('#login_username').val();
+ let password = $('#edit_password').val();
+ let confirmpassword = $('#confirm_password').val();
+ if (username.length === 0){
+ alert("Username cannot be empty");
+ return;
+ }
+ if (password.length === 0){
+ alert("Password cannot be empty");
+ return;
+ }
+ if (password !== confirmpassword){
+ alert("Password not match");
+ return;
+ }
+
+ if (confirm("Are you sure want to change Web Login Information ?")){
+ fetch("/setting/weblogin", {
+ method: "POST",
+ headers: {
+ "Content-Type": "application/x-www-form-urlencoded"
+ },
+ body: new URLSearchParams({username: username, password: password})
+ }).then(resp => {
+ if (resp.status === 200) {
+ alert("Success");
+ } else {
+ resp.text().then(text => {
+ alert("Failed to change Web Login Information : "+text);
+ });
+ }
+ })
+ }
}
\ No newline at end of file
diff --git a/config.properties b/config.properties
index 5ad7260..8a5537c 100644
--- a/config.properties
+++ b/config.properties
@@ -1,9 +1,9 @@
-#Fri Nov 08 16:52:01 WIB 2024
+#Mon Nov 11 16:04:42 WIB 2024
AudioFile01=elangWav.wav
AudioFile02=gunshotsWav.wav
AudioFile03=pinkNoiseWav.wav
-AudioFile04=04.mp3
-AudioFile05=05.mp3
+AudioFile04=
+AudioFile05=null
AudioVolumeOutput=100
Camera_Rtsp_path=/axis-media/media.amp
Camera_ip=192.168.10.17
@@ -12,13 +12,8 @@ Camera_port=80
Camera_user=root
PanTiltID=1
SerialBaudRate=9600
-SerialPort=/dev/ttyUSB0
+SerialPort=/dev/ttyAMA0
WebHost=0.0.0.0
WebPassword=bandara
WebPort=8080
WebUsername=admin
-audiofile1=
-audiofile2=
-audiofile3=
-audiofile4=
-audiofile5=
diff --git a/pom.xml b/pom.xml
index 3437fab..6ca52ab 100644
--- a/pom.xml
+++ b/pom.xml
@@ -8,11 +8,188 @@
BirdStrikeSoetta
1.0-SNAPSHOT
+
org.bytedeco
javacv-platform
- 1.5.10
+ 1.5.8
+
+
+ org.bytedeco
+ leptonica
+
+
+ org.bytedeco
+ leptonica-platform
+
+
+ org.bytedeco
+ artoolkitplus
+
+
+ org.bytedeco
+ artoolkitplus-platform
+
+
+ org.bytedeco
+ libdc1394
+
+
+ org.bytedeco
+ libdc1394-platform
+
+
+ org.bytedeco
+ libfreenect
+
+
+ org.bytedeco
+ libfreenect-platform
+
+
+ org.bytedeco
+ libfreenect2
+
+
+ org.bytedeco
+ libfreenect2-platform
+
+
+ org.bytedeco
+ flycapture
+
+
+ org.bytedeco
+ flycapture-platform
+
+
+ org.bytedeco
+ librealsense
+
+
+ org.bytedeco
+ librealsense-platform
+
+
+ org.bytedeco
+ librealsense2
+
+
+ org.bytedeco
+ librealsense2-platform
+
+
+ org.bytedeco
+ videoinput
+
+
+ org.bytedeco
+ videoinput-platform
+
+
+ org.bytedeco
+ tesseract
+
+
+ org.bytedeco
+ tesseract-platform
+
+
+
+ org.bytedeco
+ javacpp-platform
+
+
+ org.bytedeco
+ openblas-platform
+
+
+ org.bytedeco
+ opencv-platform
+
+
+ org.bytedeco
+ ffmpeg-platform
+
+
+
+
+ org.bytedeco
+ opencv
+ 4.6.0-1.5.8
+ windows-x86_64
+
+
+ org.bytedeco
+ javacpp
+ 1.5.8
+ windows-x86_64
+
+
+ org.bytedeco
+ openblas
+ 0.3.21-1.5.8
+ windows-x86_64
+
+
+ org.bytedeco
+ ffmpeg
+ 5.1.2-1.5.8
+ windows-x86_64
+
+
+
+ org.bytedeco
+ opencv
+ 4.6.0-1.5.8
+ linux-arm64
+
+
+ org.bytedeco
+ javacpp
+ 1.5.8
+ linux-arm64
+
+
+ org.bytedeco
+ openblas
+ 0.3.21-1.5.8
+ linux-arm64
+
+
+ org.bytedeco
+ ffmpeg
+ 5.1.2-1.5.8
+ linux-arm64
+
+
+
io.javalin
javalin
@@ -52,6 +229,11 @@
jackson-databind
2.17.2
+
+ com.google.code.gson
+ gson
+ 2.11.0
+
@@ -60,4 +242,13 @@
UTF-8
+
+
+
+ kr.motd.maven
+ os-maven-plugin
+ 1.7.0
+
+
+
\ No newline at end of file
diff --git a/src/main/java/Audio/AudioPlayer.java b/src/main/java/Audio/AudioPlayer.java
index a0b29d9..8056569 100644
--- a/src/main/java/Audio/AudioPlayer.java
+++ b/src/main/java/Audio/AudioPlayer.java
@@ -1,14 +1,15 @@
package Audio;
+import lombok.Getter;
import org.tinylog.Logger;
import java.io.File;
public class AudioPlayer {
- Bass bass;
- int deviceid = -1;
- boolean inited = false;
+ private final Bass bass;
+ private int deviceid = -1;
+ @Getter private boolean inited = false;
int playbackhandle = 0;
float playbackvolume = 1.0f;
@@ -48,13 +49,49 @@ public class AudioPlayer {
}
}
+ /**
+ * Get BASS_DEVICEINFO for a device
+ * @param device device id
+ * @return BASS_DEVICEINFO object or null if failed
+ */
+ public Bass.BASS_DEVICEINFO GetDeviceInfo(int device){
+ Bass.BASS_DEVICEINFO info = new Bass.BASS_DEVICEINFO();
+ if (bass.BASS_GetDeviceInfo(device, info)){
+ return info;
+ }
+ return null;
+ }
+
+ /**
+ * Find Device ID with Name
+ * @param name device name
+ * @return device id, or -1 if not found
+ */
+ public int FindDeviceIDWithName(String name){
+ int result = -1;
+ int ii = 1;
+ while(true){
+ Bass.BASS_DEVICEINFO info = new Bass.BASS_DEVICEINFO();
+ if (bass.BASS_GetDeviceInfo(ii, info)){
+ if (info.name.contains(name)){
+ result = ii;
+ break;
+ }
+ ii++;
+ } else {
+ // gak ada lagi
+ break;
+ }
+ }
+ return result;
+ }
+
/**
* Open Output Device
* @param device device id, starts from 1
* @param freq output frequency
* @return true if success
*/
- @SuppressWarnings("UnusedReturnValue")
public boolean OpenDevice(int device, int freq){
int flag = Bass.BASS_DEVICE_REINIT | Bass.BASS_DEVICE_16BITS | Bass.BASS_DEVICE_MONO | Bass.BASS_DEVICE_FREQ;
boolean success = bass.BASS_Init(device, freq, flag);
@@ -69,7 +106,8 @@ public class AudioPlayer {
}
/**
- * Set Master Volume
+ * Set Master Output Volume
+ * Master Output Volume related to the system volume (Alsamixer on Linux, Volume Mixer on Windows)
* @param value volume value, 0-100
*/
public void setMasterVolume(int value){
@@ -84,7 +122,8 @@ public class AudioPlayer {
}
/**
- * Get Master Volume
+ * Get Master Output Volume
+ * Master Output Volume related to the system volume (Alsamixer on Linux, Volume Mixer on Windows)
* @return 0 - 100, or -1 if failed
*/
@SuppressWarnings("unused")
@@ -99,6 +138,11 @@ public class AudioPlayer {
return -1;
}
+ /**
+ * Get Playback Volume
+ * is the volume of the currently playing audio file
+ * @return 0 - 100
+ */
public int getPlaybackvolume(){
if (playbackvolume<0)
return 0;
@@ -108,6 +152,11 @@ public class AudioPlayer {
return (int)(playbackvolume*100);
}
+ /**
+ * Set Playback Volume
+ * is the volume of the currently playing audio file
+ * @param value 0 - 100
+ */
public void setPlaybackvolume(int value){
if (value<0) value = 0;
if (value>100) value = 100;
@@ -119,11 +168,17 @@ public class AudioPlayer {
private float lastplaybackvolume = 1.0f;
+ /**
+ * Set Playback Volume to 0
+ */
public void Mute(){
lastplaybackvolume = playbackvolume;
setPlaybackvolume(0);
}
+ /**
+ * Set Playback Volume to last volume before Mute
+ */
public void Unmute(){
setPlaybackvolume((int)lastplaybackvolume*100);
}
@@ -164,6 +219,12 @@ public class AudioPlayer {
}
}
+ /**
+ * Play Audio File
+ * @param prop AudioFileProperties object to play
+ * @param looping set true to loop the audio file
+ * @param event PlaybackEvent object to handle playback event
+ */
public void PlayAudioFile(AudioFileProperties prop, boolean looping, PlaybackEvent event){
if (inited){
if (prop!=null){
diff --git a/src/main/java/Camera/GrabbingTask.java b/src/main/java/Camera/GrabbingTask.java
index 9e02a89..c8dcedc 100644
--- a/src/main/java/Camera/GrabbingTask.java
+++ b/src/main/java/Camera/GrabbingTask.java
@@ -9,6 +9,7 @@ import lombok.Getter;
import lombok.Setter;
import org.bytedeco.javacv.Frame;
import org.bytedeco.javacv.FrameGrabber;
+import org.tinylog.Logger;
public class GrabbingTask implements Runnable {
@Setter private Consumer
onMessageUpdate;
@@ -16,13 +17,13 @@ public class GrabbingTask implements Runnable {
@Setter private Consumer onLQFrameUpdate;
@Setter private Consumer onHQBase64Update;
@Setter private Consumer onLQBase64Update;
+ @Getter private int CaptureFPS = 0;
private final AtomicBoolean isGrabbing;
private final FrameGrabber grabber;
@Getter private final int lowquality_width = 640;
@Getter private final int lowquality_height = 360;
-
private void updateMessage(String message) {
if (onMessageUpdate != null) {
onMessageUpdate.accept(message);
@@ -68,27 +69,44 @@ public class GrabbingTask implements Runnable {
}
+ public void Stop(){
+ isGrabbing.set(false);
+ }
+ private void grabprocess() throws Exception{
+ grabber.flush();
+ Frame fr =grabber.grab();
+
+ if (fr!=null){
+ updateHQFrame(fr);
+ updateHQBase64(SomeCodes.FrameToBase64(fr));
+ Frame resized = SomeCodes.ResizeFrame(fr, lowquality_width, lowquality_height);
+ updateLQFrame(resized);
+ updateLQBase64(SomeCodes.FrameToBase64(resized));
+ } else updateMessage("Grabber returned null frame");
+ }
@Override
public void run() {
isGrabbing.set(true);
+ Logger.info("Grabbing Task started");
+ double fps = grabber.getFrameRate();
+ Logger.info("Grabber framerate = {}", fps);
+ long starttick = System.currentTimeMillis();
while (isGrabbing.get()) {
- try {
- Frame fr =grabber.grab();
- if (fr!=null){
- updateHQFrame(fr);
- updateHQBase64(SomeCodes.FrameToBase64(fr));
- Frame resized = SomeCodes.ResizeFrame(fr, lowquality_width, lowquality_height);
- updateLQFrame(resized);
- updateLQBase64(SomeCodes.FrameToBase64(resized));
- } else updateMessage("Grabber returned null frame");
- } catch (Exception e) {
- updateMessage("Error grabbing frame: " + e.getMessage());
+
+ long elapsed = System.currentTimeMillis() - starttick;
+ starttick = System.currentTimeMillis();
+ //Logger.info("Elapsed time = {} ms", elapsed);
+ if (elapsed>0) CaptureFPS = (int) (1000 / elapsed);
+ try{
+ Thread.yield();
+ grabprocess();
+ } catch (Exception e){
+ Logger.error("Error grabbing frame: "+e.getMessage());
}
}
-
-
+ Logger.info("Grabbing Task stopped");
}
}
diff --git a/src/main/java/Camera/PanTiltController.java b/src/main/java/Camera/PanTiltController.java
index cc0582b..0170344 100644
--- a/src/main/java/Camera/PanTiltController.java
+++ b/src/main/java/Camera/PanTiltController.java
@@ -3,13 +3,14 @@ package Camera;
import com.fazecast.jSerialComm.SerialPort;
import org.tinylog.Logger;
+
/**
* Pan Tilt Controller
* Using PelcoD protocol
- * Source : https://www.commfront.com/pages/pelco-d-protocol-tutorial
+ * Source : PelcoD Tutorial
*/
public class PanTiltController {
- private final SerialPort serialPort;
+ private SerialPort serialPort;
private final byte cameraid;
/**
* Open Pan Tilt Controller
@@ -17,21 +18,38 @@ public class PanTiltController {
* @param baudrate baudrate used
*/
public PanTiltController(String portname, int baudrate, int cameraid){
- serialPort = SerialPort.getCommPort(portname);
- serialPort.setBaudRate(baudrate);
this.cameraid = (byte)cameraid;
- if (serialPort.openPort()){
- Logger.info("Serial Port {} opened successfully at {}", portname, baudrate);
- } else {
- Logger.info("Failed to open Serial Port {} at {}", portname, baudrate);
- }
+ SerialPort[] comports = SerialPort.getCommPorts();
+ if (comports.length>0){
+ for (SerialPort port : comports){
+ Logger.info("Available Serial Port : {}", port.getSystemPortName());
+ if (port.getSystemPortName().equals(portname)){
+ Logger.info("Serial Port {} found", portname);
+ serialPort = port;
+
+ break;
+ }
+ }
+ if (serialPort!=null){
+ serialPort.setBaudRate(baudrate);
+ if (serialPort.openPort()){
+ Logger.info("Serial Port {} opened successfully at {}", portname, baudrate);
+ } else {
+ Logger.info("Failed to open Serial Port {} at {}", portname, baudrate);
+ }
+ } else Logger.info("Serial Port {} not found", portname);
+ } else Logger.info("No Serial Port found");
+
+
+
+
}
/**
* Close Pan Tilt Controller
*/
public void Close(){
- serialPort.closePort();
+ if (serialPort!=null) serialPort.closePort();
Logger.info("Serial Port closed");
}
diff --git a/src/main/java/Camera/RtspGrabber.java b/src/main/java/Camera/RtspGrabber.java
index 5be2449..c686b6d 100644
--- a/src/main/java/Camera/RtspGrabber.java
+++ b/src/main/java/Camera/RtspGrabber.java
@@ -7,24 +7,59 @@ import org.tinylog.Logger;
import java.util.concurrent.atomic.AtomicBoolean;
+import static Other.SomeCodes.gson;
+
public class RtspGrabber {
private final String rtspUrl;
private FFmpegFrameGrabber grabber;
private final AtomicBoolean isGrabbing = new AtomicBoolean(false);
- private @Getter Frame lastHQFrame = null;
- private @Getter Frame lastLQFrame = null;
- private @Getter String lastHQBase64 = null;
- private @Getter String lastLQBase64 = null;
+ private Frame lastHQFrame = null;
+ private Frame lastLQFrame = null;
+ private String lastHQBase64 = null;
+ private String lastLQBase64 = null;
private @Getter int HQWidth = 0;
private @Getter int HQHeight = 0;
private @Getter int LQWidth = 0;
private @Getter int LQHeight = 0;
+ private GrabbingTask grabbingTask;
public RtspGrabber(String ip, String path) {
this.rtspUrl = "rtsp://" + ip + path;
Logger.info("RtspGrabber created with url: " + rtspUrl);
}
+ private synchronized void setLastHQFrame(Frame frame){
+ lastHQFrame = frame;
+ }
+
+ public synchronized Frame getLastHQFrame(){
+ return lastHQFrame;
+ }
+
+ private synchronized void setLastLQFrame(Frame frame){
+ lastLQFrame = frame;
+ }
+
+ public synchronized Frame getLastLQFrame(){
+ return lastLQFrame;
+ }
+
+ private synchronized void setLastHQBase64(String base64){
+ lastHQBase64 = base64;
+ }
+
+ public synchronized String getLastHQBase64(){
+ return lastHQBase64;
+ }
+
+ private synchronized void setLastLQBase64(String base64){
+ lastLQBase64 = base64;
+ }
+
+ public synchronized String getLastLQBase64(){
+ return lastLQBase64;
+ }
+
/**
* Start grabbing frames from rtsp
* @param useTcp Use tcp instead of udp
@@ -34,11 +69,12 @@ public class RtspGrabber {
try{
grabber = FFmpegFrameGrabber.createDefault(rtspUrl);
if (useTcp) grabber.setOption("rtsp_transport", "tcp");
-
+ grabber.setTimeout(2000);
grabber.setImageWidth(width);
grabber.setImageHeight(height);
grabber.setPixelFormat(avutil.AV_PIX_FMT_BGR24);
grabber.start();
+
avutil.av_log_set_level(avutil.AV_LOG_ERROR);
@@ -49,7 +85,7 @@ public class RtspGrabber {
tt.setOnHQFrameUpdate(value -> {
if (value!=null){
if (value.imageWidth>0 && value.imageHeight>0){
- lastHQFrame = value;
+ setLastHQFrame(value);
HQWidth = value.imageWidth;
HQHeight = value.imageHeight;
}
@@ -59,14 +95,15 @@ public class RtspGrabber {
tt.setOnLQFrameUpdate(value -> {
if (value!=null){
if (value.imageWidth>0 && value.imageHeight>0){
- lastLQFrame = value;
+ setLastLQFrame(value);
LQWidth = value.imageWidth;
LQHeight = value.imageHeight;
}
}
});
- tt.setOnHQBase64Update(value -> lastHQBase64 = value);
- tt.setOnLQBase64Update(value -> lastLQBase64 = value);
+ tt.setOnHQBase64Update(this::setLastHQBase64);
+ tt.setOnLQBase64Update(this::setLastLQBase64);
+ grabbingTask = tt;
new Thread(tt).start();
} catch (Exception e){
@@ -78,17 +115,28 @@ public class RtspGrabber {
* Stop grabbing frames
*/
public void Stop(){
+ isGrabbing.set(false);
+ if (grabbingTask!=null){
+ grabbingTask.Stop();
+ }
+ grabbingTask = null;
if (grabber!=null) {
try{
- isGrabbing.set(false);
grabber.stop();
+ grabber.releaseUnsafe();
Logger.info("Grabber stopped");
} catch (Exception e){
Logger.error("Error stopping grabber: " + e.getMessage());
}
}
+ grabber = null;
}
+ public String LQStreamingStatus(){
+ return gson.toJson(new String[]{String.valueOf(LQWidth), String.valueOf(LQHeight) , String.valueOf(grabbingTask.getCaptureFPS())});
+ }
-
+ public String HQStreamingStatus(){
+ return gson.toJson(new String[]{String.valueOf(HQWidth), String.valueOf(HQHeight) , String.valueOf(grabbingTask.getCaptureFPS())});
+ }
}
diff --git a/src/main/java/Other/SomeCodes.java b/src/main/java/Other/SomeCodes.java
index 3e01d97..cb573fd 100644
--- a/src/main/java/Other/SomeCodes.java
+++ b/src/main/java/Other/SomeCodes.java
@@ -1,5 +1,6 @@
package Other;
+import com.google.gson.Gson;
import org.bytedeco.javacpp.Loader;
import org.bytedeco.javacv.Frame;
import org.bytedeco.javacv.Java2DFrameConverter;
@@ -42,6 +43,7 @@ public class SomeCodes {
public static final boolean haveOpenCL = opencv_core.haveOpenCL();
public static boolean useOpenCL;
private static final Base64.Encoder base64encoder = java.util.Base64.getEncoder();
+ public static final Gson gson = new Gson();
public static String[] GetAudioFiles(){
try{
@@ -49,6 +51,7 @@ public class SomeCodes {
} catch (Exception e){
Logger.error("Error getting audio files: "+e.getMessage());
}
+
return new String[0];
}
@@ -199,10 +202,15 @@ public class SomeCodes {
}
-
+ /**
+ * Load properties file
+ * @param filename properties file name
+ * @return Properties object loaded, or empty new Properties object if error
+ */
public static @NotNull Properties LoadProperties(String filename){
try{
- InputStream is = new FileInputStream(filename);
+ File ff = new File(currentDirectory, filename);
+ InputStream is = new FileInputStream(ff);
Properties prop = new Properties();
prop.load(is);
return prop;
@@ -212,9 +220,16 @@ public class SomeCodes {
return new Properties();
}
+ /**
+ * Save properties file
+ * @param prop Properties object to save
+ * @param filename properties file name
+ * @return true if success, false otherwise
+ */
public static boolean SaveProperties(Properties prop, String filename){
try{
- OutputStream os = new FileOutputStream(filename);
+ File ff = new File(currentDirectory, filename);
+ OutputStream os = new FileOutputStream(ff);
prop.store(os, null);
return true;
} catch (Exception e){
@@ -236,6 +251,7 @@ public class SomeCodes {
UMat src = new UMat();
source.copyTo(src);
UMat dst = new UMat();
+
opencv_imgproc.resize(src, dst, sz);
dst.copyTo(dest);
} else {
@@ -249,4 +265,19 @@ public class SomeCodes {
Mat resized = ResizeMat(mat, width, height);
return matConverter.convert(resized);
}
+
+ /**
+ * check if an ip address is reachable
+ * @param ipaddress ip address to check
+ * @return true if valid and reachable, false otherwise
+ */
+ public static boolean IpIsReachable(String ipaddress){
+ try{
+ InetAddress inet = InetAddress.getByName(ipaddress);
+ return inet.isReachable(1000);
+ } catch (Exception e){
+ Logger.error("Error checking ip address: "+e.getMessage());
+ }
+ return false;
+ }
}
diff --git a/src/main/java/SBC/CpuInfo.java b/src/main/java/SBC/CpuInfo.java
new file mode 100644
index 0000000..f7bff26
--- /dev/null
+++ b/src/main/java/SBC/CpuInfo.java
@@ -0,0 +1,8 @@
+package SBC;
+
+public class CpuInfo {
+ public int processorCount;
+ public String revision;
+ public String serial;
+ public String model;
+}
diff --git a/src/main/java/SBC/GPIO.java b/src/main/java/SBC/GPIO.java
index 0d5f80e..1deadd4 100644
--- a/src/main/java/SBC/GPIO.java
+++ b/src/main/java/SBC/GPIO.java
@@ -6,7 +6,6 @@ import org.tinylog.Logger;
import java.nio.file.Files;
import java.nio.file.Path;
-@SuppressWarnings("unused")
public class GPIO {
private static final Path gpioPath = Path.of("/sys/class/gpio");
@@ -14,19 +13,15 @@ public class GPIO {
private static final Path gpioUnexportPath = Path.of("/sys/class/gpio/unexport");
- public static boolean IsRaspberry64(){
+ public static boolean HaveGPIO(){
if (Platform.isLinux()){
- if (Platform.isARM()){
- if (Platform.is64Bit()){
- if (gpioPath.toFile().isDirectory()){
- if (gpioExportPath.toFile().isFile()){
- if (gpioUnexportPath.toFile().isFile()){
- return true;
- } else Logger.error("GPIO unexport path is not found");
- } else Logger.error("GPIO export path is not found");
- } else Logger.error("GPIO path is not found");
- } else Logger.info("Device is not 64 bit");
- } else Logger.info("Device is not ARM");
+ if (gpioPath.toFile().isDirectory()){
+ if (gpioExportPath.toFile().isFile()){
+ if (gpioUnexportPath.toFile().isFile()){
+ return true;
+ } else Logger.error("GPIO unexport path is not found");
+ } else Logger.error("GPIO export path is not found");
+ } else Logger.error("GPIO path is not found");
} else Logger.info("OS is not Linux");
return false;
}
diff --git a/src/main/java/SBC/NetworkTransmitReceiveInfo.java b/src/main/java/SBC/NetworkTransmitReceiveInfo.java
new file mode 100644
index 0000000..03d5917
--- /dev/null
+++ b/src/main/java/SBC/NetworkTransmitReceiveInfo.java
@@ -0,0 +1,84 @@
+package SBC;
+
+import org.jetbrains.annotations.Nullable;
+
+import java.util.Objects;
+
+import static Other.SomeCodes.ValidString;
+
+public class NetworkTransmitReceiveInfo {
+ public String name;
+ public long bytesReceived;
+ public long packetsReceived;
+ public long errorsReceived;
+ public long droppedReceived;
+ public long fifoReceived;
+ public long frameReceived;
+ public long compressedReceived;
+ public long multicastReceived;
+ public long bytesTransmitted;
+ public long packetsTransmitted;
+ public long errorsTransmitted;
+ public long droppedTransmitted;
+ public long fifoTransmitted;
+ public long collsTransmitted;
+ public long carrierTransmitted;
+ public long compressedTransmitted;
+ public long timetick;
+
+ /**
+ * Calculate the download speed
+ * @param prev Previous NetworkTransmitReceiveInfo
+ * @param unit Speed unit (KB, MB, GB)
+ * @return Download speed in {unit}/second
+ */
+ public double RxSpeed(NetworkTransmitReceiveInfo prev, String unit){
+ if (prev!=null){
+ if (Objects.equals(prev.name, name)){
+ long timeDiff = timetick - prev.timetick;
+ if (timeDiff>0){
+ long bytesDiff = bytesReceived - prev.bytesReceived;
+ if (ValidString(unit)) unit = unit.toUpperCase();
+ Double speed = ConvertToUnit(unit, timeDiff, bytesDiff);
+ if (speed != null) return speed;
+ }
+ }
+ }
+ return 0;
+ }
+
+ @Nullable
+ private Double ConvertToUnit(String unit, long timeDiff, long bytesDiff) {
+ if (bytesDiff>0){
+ double speed = ((double) bytesDiff / timeDiff) * 1000;
+ return switch (unit) {
+ case "KB" -> speed / 1024;
+ case "MB" -> speed / 1024 / 1024;
+ case "GB" -> speed / 1024 / 1024 / 1024;
+ default -> speed;
+ };
+ }
+ return null;
+ }
+
+ /**
+ * Calculate the upload speed
+ * @param prev Previous NetworkTransmitReceiveInfo
+ * @param unit Speed unit (KB, MB, GB)
+ * @return Upload speed in {unit}/second
+ */
+ public double TxSpeed(NetworkTransmitReceiveInfo prev, String unit){
+ if (prev!=null){
+ if (Objects.equals(prev.name, name)){
+ long timeDiff = timetick - prev.timetick;
+ if (timeDiff>0){
+ long bytesDiff = bytesTransmitted - prev.bytesTransmitted;
+ if (ValidString(unit)) unit = unit.toUpperCase();
+ Double speed = ConvertToUnit(unit, timeDiff, bytesDiff);
+ if (speed != null) return speed;
+ }
+ }
+ }
+ return 0;
+ }
+}
diff --git a/src/main/java/SBC/ProcessorStatus.java b/src/main/java/SBC/ProcessorStatus.java
new file mode 100644
index 0000000..355c041
--- /dev/null
+++ b/src/main/java/SBC/ProcessorStatus.java
@@ -0,0 +1,45 @@
+package SBC;
+
+public class ProcessorStatus {
+ public String name;
+ public int user;
+ public int nice;
+ public int system;
+ public int idle;
+ public int iowait;
+ public int irq;
+ public int softirq;
+ public int steal;
+ public int guest;
+ public int guest_nice;
+
+ /**
+ * Calculate total CPU time
+ * @return Total CPU time
+ */
+ public int total_time(){
+ return user + nice + system + idle + iowait + irq + softirq + steal + guest + guest_nice;
+ }
+
+ /**
+ * Calculate idle CPU time
+ * @return Idle CPU time
+ */
+ public int idle_time(){
+ return idle + iowait;
+ }
+
+ /**
+ * Calculate CPU usage percentage
+ * @param prev Previous CPU information
+ * @return CPU usage percentage 0 - 100
+ */
+ public int cpu_usage(ProcessorStatus prev){
+ if (prev!=null){
+ int total_diff = total_time() - prev.total_time();
+ int idle_diff = idle_time() - prev.idle_time();
+ return (int)(100.0 * (total_diff - idle_diff) / total_diff);
+ }
+ return 0;
+ }
+}
diff --git a/src/main/java/SBC/RamInformation.java b/src/main/java/SBC/RamInformation.java
new file mode 100644
index 0000000..d9fc08c
--- /dev/null
+++ b/src/main/java/SBC/RamInformation.java
@@ -0,0 +1,12 @@
+package SBC;
+
+public class RamInformation {
+ public int totalKB;
+ public int usedKB;
+ public int availableKB;
+ public int swapTotalKB;
+ public int swapFreeKB;
+ public double RamUsagePercentage(){
+ return (double) usedKB / totalKB * 100;
+ }
+}
diff --git a/src/main/java/SBC/SystemInformation.java b/src/main/java/SBC/SystemInformation.java
new file mode 100644
index 0000000..d5d045f
--- /dev/null
+++ b/src/main/java/SBC/SystemInformation.java
@@ -0,0 +1,179 @@
+package SBC;
+
+import com.sun.jna.Platform;
+
+import java.io.File;
+import java.nio.file.Files;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public class SystemInformation {
+
+
+
+ public static int getCPUTemperature() {
+ if (Platform.isLinux()){
+ File ff = new File("/sys/class/thermal/thermal_zone0/temp");
+ if (ff.isFile() && ff.canRead()){
+ try{
+ String value = Files.readString(ff.toPath()).trim();
+ return Integer.parseInt(value) / 1000;
+ } catch (Exception ignored) {
+ }
+ }
+ }
+ return 0;
+ }
+
+ public static NetworkTransmitReceiveInfo[] getNetworkTransmitReceiveInfo(){
+ if (Platform.isLinux()){
+ File ff = new File("/proc/net/dev");
+ if (ff.isFile() && ff.canRead()){
+ List result = new ArrayList<>();
+ final Pattern pattern = Pattern.compile("\\s+(.*):\\s+(\\d+)\\s+(\\d+)\\s+(\\d+)\\s+(\\d+)\\s+(\\d+)\\s+(\\d+)\\s+(\\d+)\\s+(\\d+)\\s+(\\d+)\\s+(\\d+)\\s+(\\d+)\\s+(\\d+)\\s+(\\d+)\\s+(\\d+)\\s+(\\d+)\\s+(\\d+)");
+ try{
+ String[] lines = Files.readString(ff.toPath()).split("\n");
+ for (String line : lines){
+ Matcher m = pattern.matcher(line);
+ if (m.find()){
+ NetworkTransmitReceiveInfo info = new NetworkTransmitReceiveInfo();
+ info.name = m.group(1).trim();
+ info.bytesReceived = Long.parseLong(m.group(2));
+ info.packetsReceived = Long.parseLong(m.group(3));
+ info.errorsReceived = Long.parseLong(m.group(4));
+ info.droppedReceived = Long.parseLong(m.group(5));
+ info.fifoReceived = Long.parseLong(m.group(6));
+ info.frameReceived = Long.parseLong(m.group(7));
+ info.compressedReceived = Long.parseLong(m.group(8));
+ info.multicastReceived = Long.parseLong(m.group(9));
+ info.bytesTransmitted = Long.parseLong(m.group(10));
+ info.packetsTransmitted = Long.parseLong(m.group(11));
+ info.errorsTransmitted = Long.parseLong(m.group(12));
+ info.droppedTransmitted = Long.parseLong(m.group(13));
+ info.fifoTransmitted = Long.parseLong(m.group(14));
+ info.collsTransmitted = Long.parseLong(m.group(15));
+ info.carrierTransmitted = Long.parseLong(m.group(16));
+ info.compressedTransmitted = Long.parseLong(m.group(17));
+ info.timetick = System.currentTimeMillis();
+ result.add(info);
+ }
+ }
+ } catch (Exception ignored) {
+
+ }
+ return result.toArray(new NetworkTransmitReceiveInfo[0]);
+ }
+ }
+ return new NetworkTransmitReceiveInfo[0];
+ }
+
+ public static CpuInfo getCPUInfo(){
+ CpuInfo result = new CpuInfo();
+ if (Platform.isLinux()){
+ File ff = new File("/proc/cpuinfo");
+ if (ff.isFile() && ff.canRead()){
+ final Pattern pattern = Pattern.compile( "\\s*(.*):\\s*(.*)");
+ try{
+ String[] lines = Files.readString(ff.toPath()).split("\n");
+ for (String line : lines){
+ Matcher m = pattern.matcher(line);
+ if (m.find()){
+ String key = m.group(1).trim();
+ String value = m.group(2).trim();
+ switch (key){
+ case "processor":
+ result.processorCount++;
+ break;
+ case "Revision":
+ result.revision = value;
+ break;
+ case "Serial":
+ result.serial = value;
+ break;
+ case "Model":
+ result.model = value;
+ break;
+ }
+ }
+ }
+ } catch (Exception ignored) {
+ }
+ }
+ }
+ return result;
+ }
+
+ public static ProcessorStatus[] getProcStat(){
+ if (Platform.isLinux()){
+ File ff = new File("/proc/stat");
+ if (ff.isFile() && ff.canRead()){
+ final Pattern pattern = Pattern.compile( "(cpu\\d?)\\s+(\\d+)\\s+(\\d+)\\s+(\\d+)\\s+(\\d+)\\s+(\\d+)\\s+(\\d+)\\s+(\\d+)\\s+(\\d+)\\s+(\\d+)\\s+(\\d+)");
+ List result = new ArrayList<>();
+ try{
+ String[] lines = Files.readString(ff.toPath()).split("\n");
+ for (String line : lines){
+ Matcher m = pattern.matcher(line);
+ if (m.find()){
+ ProcessorStatus info = new ProcessorStatus();
+ info.name = m.group(1).trim();
+ info.user = Integer.parseInt(m.group(2));
+ info.nice = Integer.parseInt(m.group(3));
+ info.system = Integer.parseInt(m.group(4));
+ info.idle = Integer.parseInt(m.group(5));
+ info.iowait = Integer.parseInt(m.group(6));
+ info.irq = Integer.parseInt(m.group(7));
+ info.softirq = Integer.parseInt(m.group(8));
+ info.steal = Integer.parseInt(m.group(9));
+ info.guest = Integer.parseInt(m.group(10));
+ info.guest_nice = Integer.parseInt(m.group(11));
+ result.add(info);
+ }
+ }
+ return result.toArray(new ProcessorStatus[0]);
+ } catch (Exception ignored) {
+ }
+ }
+ }
+ return new ProcessorStatus[0];
+ }
+
+ public static RamInformation getRAMInformation(){
+
+ RamInformation result = new RamInformation();
+ if (Platform.isLinux()){
+ File ff = new File("/proc/meminfo");
+ if (ff.isFile() && ff.canRead()){
+ final Pattern pattern = Pattern.compile("(.*):\\s+(\\d+).kB");
+ try{
+ String[] lines = Files.readString(ff.toPath()).split("\n");
+ for (String line : lines) {
+ Matcher m = pattern.matcher(line);
+ if (m.find()){
+ String key = m.group(1);
+ int value = Integer.parseInt(m.group(2));
+ switch (key){
+ case "MemTotal":
+ result.totalKB = value;
+ break;
+ case "MemAvailable":
+ result.availableKB = value;
+ break;
+ case "SwapTotal":
+ result.swapTotalKB = value;
+ break;
+ case "SwapFree":
+ result.swapFreeKB = value;
+ break;
+ }
+ }
+ }
+ } catch (Exception ignored) {
+ }
+ result.usedKB = result.totalKB - result.availableKB;
+ }
+ }
+ return result;
+ }
+}
diff --git a/src/main/java/Web/AudioFilesInfo.java b/src/main/java/Web/AudioFilesInfo.java
new file mode 100644
index 0000000..89a1640
--- /dev/null
+++ b/src/main/java/Web/AudioFilesInfo.java
@@ -0,0 +1,9 @@
+package Web;
+
+public class AudioFilesInfo {
+ public String preset1;
+ public String preset2;
+ public String preset3;
+ public String preset4;
+ public String preset5;
+}
diff --git a/src/main/java/Web/WebServer.java b/src/main/java/Web/WebServer.java
index a263d1d..a147072 100644
--- a/src/main/java/Web/WebServer.java
+++ b/src/main/java/Web/WebServer.java
@@ -3,12 +3,14 @@ package Web;
import Other.SomeCodes;
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.nio.file.Files;
-import java.nio.file.Path;
+import java.util.List;
import java.util.Objects;
import java.util.Properties;
import java.util.Set;
@@ -20,20 +22,24 @@ 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 connectedWebsocketClients = ConcurrentHashMap.newKeySet();
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("1");
- String audiofile2 = ctx.formParam("2");
- String audiofile3 = ctx.formParam("3");
- String audiofile4 = ctx.formParam("4");
- String audiofile5 = ctx.formParam("5");
+ 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);
@@ -41,41 +47,59 @@ public class WebServer {
Logger.info("audiofile5: {}", audiofile5);
Properties prop = SomeCodes.LoadProperties("config.properties");
- prop.setProperty("audiofile1", audiofile1!=null?audiofile1:"");
- prop.setProperty("audiofile2", audiofile2!=null?audiofile2:"");
- prop.setProperty("audiofile3", audiofile3!=null?audiofile3:"");
- prop.setProperty("audiofile4", audiofile4!=null?audiofile4:"");
- prop.setProperty("audiofile5", audiofile5!=null?audiofile5:"");
+ 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 -> {
- UploadedFile file = ctx.uploadedFile("file");
- if (file!=null){
- try {
- Path targetsave = audioPath.resolve(file.filename());
- Files.copy(file.content(), targetsave);
- Logger.info("Uploaded file: {}, size: {} saved at {}", file.filename(),file.size(), targetsave);
- } catch (Exception e){
- Logger.error("Failed to save uploaded file: {}, Message: {}", file.filename(), e.getMessage());
- }
+ List 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")){
- ctx.status(200);
+ 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 -> {
@@ -83,6 +107,11 @@ public class WebServer {
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");
@@ -90,9 +119,13 @@ public class WebServer {
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");
}
}));
@@ -103,7 +136,7 @@ public class WebServer {
if (ctx.sessionAttribute("username")==null) {
// belum login
ctx.redirect("/login.html");
- } else if (Objects.equals(ctx.sessionAttribute("username"), webusername)){
+ } else if (Objects.equals(ctx.sessionAttribute("username"), this.webusername)){
// sudah login
ctx.redirect("/index.html");
} else {
@@ -127,11 +160,12 @@ public class WebServer {
app.post("/login", ctx ->{
String username = ctx.formParam("username");
String password = ctx.formParam("password");
- if (Objects.equals(username, webusername) && Objects.equals(password, webpassword)){
+ if (Objects.equals(username, this.webusername) && Objects.equals(password, this.webpassword)){
ctx.sessionAttribute("username", username);
ctx.redirect("/index.html");
} else {
- ctx.redirect("/login.html?error=Invalid username or password");
+ ctx.status(400);
+ ctx.redirect("/login.html");
}
});
@@ -151,9 +185,12 @@ public class WebServer {
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);
}
});
@@ -196,13 +233,13 @@ public class WebServer {
}
WsConnectHandler connectws = ws ->{
- Logger.info("WebSocket connected from {}", ws.host());
+ 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.host(), ws.status(), ws.reason());
+ Logger.info("WebSocket closed from {}, code {}, reason {}", ws.sessionId(), ws.status(), ws.reason());
connectedWebsocketClients.remove(ws);
};
diff --git a/src/main/java/Web/WebsocketEvent.java b/src/main/java/Web/WebsocketEvent.java
index fa352eb..dd55039 100644
--- a/src/main/java/Web/WebsocketEvent.java
+++ b/src/main/java/Web/WebsocketEvent.java
@@ -3,4 +3,5 @@ package Web;
public interface WebsocketEvent {
String onMessage(String message);
WebsocketReply onWebsocketCommand(WebsocketCommand command);
+ void NewCameraConfiguration();
}
diff --git a/src/main/java/id/co/gtc/Main.java b/src/main/java/id/co/gtc/Main.java
index 41ccf49..b894008 100644
--- a/src/main/java/id/co/gtc/Main.java
+++ b/src/main/java/id/co/gtc/Main.java
@@ -2,22 +2,23 @@ package id.co.gtc;
import Audio.AudioFileProperties;
import Audio.AudioPlayer;
+import Audio.Bass;
import Audio.PlaybackEvent;
import Camera.PanTiltController;
import Camera.RtspGrabber;
import Camera.VapixProtocol;
import Other.SomeCodes;
-import Web.WebServer;
-import Web.WebsocketCommand;
-import Web.WebsocketEvent;
-import Web.WebsocketReply;
+import SBC.ProcessorStatus;
+import SBC.RamInformation;
+import SBC.SystemInformation;
+import Web.*;
+import com.google.gson.JsonObject;
import org.bytedeco.opencv.global.opencv_core;
import org.tinylog.Logger;
import java.io.File;
import java.nio.file.Path;
-import java.util.Objects;
-import java.util.Properties;
+import java.util.*;
import static Other.SomeCodes.*;
@@ -28,6 +29,11 @@ public class Main {
private static PanTiltController panTiltController;
private static AudioFileProperties audioFileProperties;
private static VapixProtocol vapixProtocol;
+ private static Timer timer;
+ private static int cpuTemperature;
+ private static RamInformation ramInformation;
+ private static ProcessorStatus[] previousCpuInfo;
+ private static final Map cpuUsage = new HashMap<>();
// Application start from here
public static void main(String[] args) {
@@ -37,8 +43,11 @@ public class Main {
if (rtspGrabber!=null) rtspGrabber.Stop();
if (panTiltController!=null) panTiltController.Close();
if (vapixProtocol!=null) vapixProtocol.Close();
+ if (timer!=null) timer.cancel();
}));
+ init_system_monitoring();
+
init_properties();
init_audiofiles();
@@ -49,6 +58,29 @@ public class Main {
init_Vapix();
}
+ private static void init_system_monitoring(){
+ TimerTask tt = new TimerTask() {
+ @Override
+ public void run() {
+ cpuTemperature = SystemInformation.getCPUTemperature();
+ ramInformation = SystemInformation.getRAMInformation();
+ ProcessorStatus[] cpuinfo = SystemInformation.getProcStat();
+ if (cpuinfo.length>0){
+ if (previousCpuInfo==null || !Objects.equals(previousCpuInfo.length, cpuinfo.length)){
+ previousCpuInfo = cpuinfo;
+ } else {
+ for(int ii=0;ii0){
+ Bass.BASS_DEVICEINFO info = audioPlayer.GetDeviceInfo(devid);
+ if (audioPlayer.OpenDevice(devid,48000)){
+ audioPlayer.setMasterVolume(100);
+ audioPlayer.setPlaybackvolume(100);
+ Logger.info("Audio Device ID={} opened : {}", devid, info.name);
+ } else Logger.error("Failed to open Audio Device ID={}", devid);
+ } else Logger.error("USB Audio Device not found");
}
static PlaybackEvent pe = new PlaybackEvent() {
@@ -217,6 +262,7 @@ public class Main {
audioFileProperties = afp;
audioPlayer.PlayAudioFile(afp, true, pe);
return new WebsocketReply("PLAY AUDIO", afp.filename);
+
} else return new WebsocketReply("PLAY AUDIO", "Failed to open audio file "+filename);
} else return new WebsocketReply("PLAY AUDIO", "Audio file not found : "+filename);
} else return new WebsocketReply("PLAY AUDIO", String.format("AudioFile with ID %02d not found", id));
@@ -252,20 +298,64 @@ public class Main {
case "GET BASE64":
if (rtspGrabber!=null){
if (Objects.equals(command.data,"HQ"))
- return new WebsocketReply("GET BASE64", "data:image/jpeg;base64,"+ rtspGrabber.getLastHQBase64(), String.format("Streaming at %dx%d", rtspGrabber.getHQWidth(), rtspGrabber.getHQHeight()));
+ return new WebsocketReply("GET BASE64", "data:image/jpeg;base64,"+ rtspGrabber.getLastHQBase64(), rtspGrabber.HQStreamingStatus());
else
- return new WebsocketReply("GET BASE64", "data:image/jpeg;base64,"+ rtspGrabber.getLastLQBase64(), String.format("Streaming at %dx%d", rtspGrabber.getLQWidth(), rtspGrabber.getLQHeight()));
+ return new WebsocketReply("GET BASE64", "data:image/jpeg;base64,"+ rtspGrabber.getLastLQBase64(), rtspGrabber.LQStreamingStatus());
} else return new WebsocketReply("GET BASE64", "RTSP Grabber not initialized");
case "GET RESOLUTION":
if (vapixProtocol!=null){
int[] res = vapixProtocol.GetCurrentResolution(1);
return new WebsocketReply("GET RESOLUTION", String.format("%dx%d", res[0], res[1]));
} else return new WebsocketReply("GET RESOLUTION", "VapixProtocol not initialized");
-
+ case "GET AUDIOFILES":
+ AudioFilesInfo afi = new AudioFilesInfo();
+ afi.preset1 = GetConfigAudioFile(1);
+ afi.preset2 = GetConfigAudioFile(2);
+ afi.preset3 = GetConfigAudioFile(3);
+ afi.preset4 = GetConfigAudioFile(4);
+ afi.preset5 = GetConfigAudioFile(5);
+ return new WebsocketReply("GET AUDIOFILES", gson.toJson(afi));
+ case "GET SYSTEM INFO":
+ JsonObject data = new JsonObject();
+ data.addProperty("cpu_temperature", String.valueOf(cpuTemperature));
+ if (ramInformation!=null) {
+ data.addProperty("ram_usage", String.format("%.1f", ramInformation.RamUsagePercentage()));
+ }
+ if (!cpuUsage.isEmpty()) {
+ for(String key : cpuUsage.keySet()){
+ data.addProperty(key, String.valueOf(cpuUsage.get(key)));
+ }
+ }
+ return new WebsocketReply("GET SYSTEM INFO", data.toString());
default:
return new WebsocketReply("UNKNOWN COMMAND", command.command);
}
}
+
+ @Override
+ public void NewCameraConfiguration() {
+ Logger.info("New Camera Configuration detected");
+ Properties prop = SomeCodes.LoadProperties("config.properties");
+ String camera_ip = prop.getProperty("Camera_ip");
+ String camera_port = prop.getProperty("Camera_port");
+ String camera_user = prop.getProperty("Camera_user");
+ String camera_password = prop.getProperty("Camera_password");
+ String camera_rtsp_path = prop.getProperty("Camera_Rtsp_path");
+ Logger.info("Camera Ip: "+camera_ip);
+ Logger.info("Camera Port: "+camera_port);
+ Logger.info("Camera User: "+camera_user);
+ Logger.info("Camera Password: "+camera_password);
+ Logger.info("Camera Rtsp Path: "+camera_rtsp_path);
+
+ if (rtspGrabber!=null) rtspGrabber.Stop();
+ init_rtspgrabber();
+ Logger.info("RtspGrabber recreated");
+
+ if (vapixProtocol!=null) vapixProtocol.Close();
+ init_Vapix();
+ Logger.info("VapixProtocol recreated");
+
+ }
};
private static void init_webserver() {