Add more functions
This commit is contained in:
@@ -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){
|
||||
|
||||
@@ -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<String> onMessageUpdate;
|
||||
@@ -16,13 +17,13 @@ public class GrabbingTask implements Runnable {
|
||||
@Setter private Consumer<Frame> onLQFrameUpdate;
|
||||
@Setter private Consumer<String> onHQBase64Update;
|
||||
@Setter private Consumer<String> 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");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 : <a href="https://www.commfront.com/pages/pelco-d-protocol-tutorial">PelcoD Tutorial</a>
|
||||
*/
|
||||
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");
|
||||
}
|
||||
|
||||
|
||||
@@ -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())});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
8
src/main/java/SBC/CpuInfo.java
Normal file
8
src/main/java/SBC/CpuInfo.java
Normal file
@@ -0,0 +1,8 @@
|
||||
package SBC;
|
||||
|
||||
public class CpuInfo {
|
||||
public int processorCount;
|
||||
public String revision;
|
||||
public String serial;
|
||||
public String model;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
84
src/main/java/SBC/NetworkTransmitReceiveInfo.java
Normal file
84
src/main/java/SBC/NetworkTransmitReceiveInfo.java
Normal file
@@ -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;
|
||||
}
|
||||
}
|
||||
45
src/main/java/SBC/ProcessorStatus.java
Normal file
45
src/main/java/SBC/ProcessorStatus.java
Normal file
@@ -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;
|
||||
}
|
||||
}
|
||||
12
src/main/java/SBC/RamInformation.java
Normal file
12
src/main/java/SBC/RamInformation.java
Normal file
@@ -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;
|
||||
}
|
||||
}
|
||||
179
src/main/java/SBC/SystemInformation.java
Normal file
179
src/main/java/SBC/SystemInformation.java
Normal file
@@ -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<NetworkTransmitReceiveInfo> 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<ProcessorStatus> 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;
|
||||
}
|
||||
}
|
||||
9
src/main/java/Web/AudioFilesInfo.java
Normal file
9
src/main/java/Web/AudioFilesInfo.java
Normal file
@@ -0,0 +1,9 @@
|
||||
package Web;
|
||||
|
||||
public class AudioFilesInfo {
|
||||
public String preset1;
|
||||
public String preset2;
|
||||
public String preset3;
|
||||
public String preset4;
|
||||
public String preset5;
|
||||
}
|
||||
@@ -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<WsContext> 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<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")){
|
||||
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);
|
||||
};
|
||||
|
||||
|
||||
@@ -3,4 +3,5 @@ package Web;
|
||||
public interface WebsocketEvent {
|
||||
String onMessage(String message);
|
||||
WebsocketReply onWebsocketCommand(WebsocketCommand command);
|
||||
void NewCameraConfiguration();
|
||||
}
|
||||
|
||||
@@ -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<String, Integer> 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;ii<previousCpuInfo.length;ii++){
|
||||
cpuUsage.put(cpuinfo[ii].name, cpuinfo[ii].cpu_usage(previousCpuInfo[ii]));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
timer = new Timer();
|
||||
timer.scheduleAtFixedRate(tt, 1000, 5000);
|
||||
|
||||
}
|
||||
|
||||
private static void init_properties(){
|
||||
if (ExtractResource("/tinylog.properties", currentDirectory)==null) Logger.error("Failed to extract tinylog.properties");
|
||||
if (ExtractResource("/config.properties", currentDirectory)==null) Logger.error("Failed to extract config.properties");
|
||||
@@ -73,21 +105,24 @@ public class Main {
|
||||
String username = config.getProperty("Camera_user");
|
||||
String password = config.getProperty("Camera_password");
|
||||
if (ValidString(ip)){
|
||||
if (ValidInteger(port)){
|
||||
if (ValidPortNumber(port)){
|
||||
if (ValidString(username)){
|
||||
if (ValidString(password)){
|
||||
vapixProtocol = new VapixProtocol(ip, Integer.parseInt(port), username, password);
|
||||
Logger.info("Camera Product Number: "+vapixProtocol.GetProductNumber());
|
||||
Logger.info("Camera Serial Number: "+vapixProtocol.GetSerialNumber());
|
||||
if (vapixProtocol.PTZEnabled()){
|
||||
Logger.info("PTZ Enabled");
|
||||
} else Logger.error("PTZ Disabled");
|
||||
Logger.info("Max Zoom: "+vapixProtocol.GetPTZMaxZoom());
|
||||
Logger.info("Min Zoom: "+vapixProtocol.GetPTZMinZoom());
|
||||
} else Logger.error("Invalid Camera Password");
|
||||
} else Logger.error("Invalid Camera Username");
|
||||
} else Logger.error("Invalid Camera Port");
|
||||
} else Logger.error("Invalid Camera IP");
|
||||
if (IpIsReachable(ip)){
|
||||
Logger.info("Camera IP is reachable");
|
||||
vapixProtocol = new VapixProtocol(ip, Integer.parseInt(port), username, password);
|
||||
Logger.info("Camera Product Number: "+vapixProtocol.GetProductNumber());
|
||||
Logger.info("Camera Serial Number: "+vapixProtocol.GetSerialNumber());
|
||||
if (vapixProtocol.PTZEnabled()){
|
||||
Logger.info("PTZ Enabled");
|
||||
} else Logger.error("PTZ Disabled");
|
||||
Logger.info("Max Zoom: "+vapixProtocol.GetPTZMaxZoom());
|
||||
Logger.info("Min Zoom: "+vapixProtocol.GetPTZMinZoom());
|
||||
} else Logger.error("Camera IP is not reachable");
|
||||
} else Logger.error("Camera Password is not valid string");
|
||||
} else Logger.error("Camera Username is not valid string");
|
||||
} else Logger.error("Camera Port is not valid");
|
||||
} else Logger.error( "Camera IP is not valid string");
|
||||
}
|
||||
|
||||
private static void init_pantiltcontroller() {
|
||||
@@ -112,22 +147,32 @@ public class Main {
|
||||
Properties config = SomeCodes.LoadProperties("config.properties");
|
||||
String targetip = config.getProperty("Camera_ip");
|
||||
String rtsppath = config.getProperty("Camera_Rtsp_path");
|
||||
rtspGrabber = null;
|
||||
if (ValidString(targetip)){
|
||||
if (ValidString(rtsppath)){
|
||||
rtspGrabber = new RtspGrabber(targetip, rtsppath);
|
||||
|
||||
|
||||
rtspGrabber.Start(true, 1920, 1080);
|
||||
} else Logger.error("Invalid Camera Path");
|
||||
} else Logger.error("Invalid Camera IP");
|
||||
if (IpIsReachable(targetip)){
|
||||
Logger.info("Camera IP is reachable");
|
||||
rtspGrabber = new RtspGrabber(targetip, rtsppath);
|
||||
rtspGrabber.Start(true, 1920, 1080);
|
||||
} else Logger.error("Camera IP is not reachable");
|
||||
} else Logger.error("Camera Path is not valid string");
|
||||
} else Logger.error("Camera IP is not valid string");
|
||||
}
|
||||
|
||||
private static void init_audio() {
|
||||
audioPlayer = new AudioPlayer();
|
||||
audioPlayer.DetectOutputDevices();
|
||||
audioPlayer.OpenDevice(1,48000);
|
||||
audioPlayer.setMasterVolume(100);
|
||||
audioPlayer.setPlaybackvolume(100);
|
||||
int devid = audioPlayer.FindDeviceIDWithName("USB");
|
||||
if (devid<1) devid = audioPlayer.FindDeviceIDWithName("Speakers");
|
||||
|
||||
if (devid>0){
|
||||
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() {
|
||||
|
||||
Reference in New Issue
Block a user