Compare commits

6 Commits

Author SHA1 Message Date
a1b6ec54ab Patch 17/03/2025 2025-03-17 13:35:05 +07:00
123a89eec9 Patch 04/03/2025 2025-03-04 12:25:02 +07:00
e1d129fa07 Kirim ke Bandara 27/02/2025 2025-02-27 15:11:56 +07:00
5f8d1946c0 YOLODetector is working (25/02/2025) 2025-02-25 13:56:57 +07:00
ce5c8d5946 Change SBC to Jetson Orin 2025-02-25 07:35:38 +07:00
21e8ab1e82 Change SBC to Jetson Orin 2024-12-03 15:59:18 +07:00
31 changed files with 2289 additions and 437 deletions

View File

@@ -4,6 +4,7 @@
<inspection_tool class="ExtractMethodRecommender" enabled="true" level="WARNING" enabled_by_default="true"> <inspection_tool class="ExtractMethodRecommender" enabled="true" level="WARNING" enabled_by_default="true">
<option name="minLength" value="745" /> <option name="minLength" value="745" />
</inspection_tool> </inspection_tool>
<inspection_tool class="GrazieInspection" enabled="false" level="GRAMMAR_ERROR" enabled_by_default="false" />
<inspection_tool class="HttpUrlsUsage" enabled="true" level="WEAK WARNING" enabled_by_default="true"> <inspection_tool class="HttpUrlsUsage" enabled="true" level="WEAK WARNING" enabled_by_default="true">
<option name="ignoredUrls"> <option name="ignoredUrls">
<list> <list>
@@ -35,6 +36,7 @@
</list> </list>
</option> </option>
</inspection_tool> </inspection_tool>
<inspection_tool class="LanguageDetectionInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="MethodNameSameAsClassName" enabled="false" level="WARNING" enabled_by_default="false" /> <inspection_tool class="MethodNameSameAsClassName" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="RedundantCast" enabled="false" level="WARNING" enabled_by_default="false" /> <inspection_tool class="RedundantCast" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SpellCheckingInspection" enabled="false" level="TYPO" enabled_by_default="false"> <inspection_tool class="SpellCheckingInspection" enabled="false" level="TYPO" enabled_by_default="false">

View File

@@ -4,13 +4,14 @@ Camera_port = 80
Camera_user = root Camera_user = root
Camera_password = password Camera_password = password
Camera_Rtsp_path = /axis-media/media.amp Camera_Rtsp_path = /axis-media/media.amp
#Camera_Rtsp_path = /video1
AudioFile01 = elangWav.wav AudioFile01 = elangWav.wav
AudioFile02 = gunshotsWav.wav AudioFile02 = gunshotsWav.wav
AudioFile03 = pinkNoiseWav.wav AudioFile03 = pinkNoiseWav.wav
AudioFile04 = 04.mp3 AudioFile04 = 04.mp3
AudioFile05 = 05.mp3 AudioFile05 = 05.mp3
AudioVolumeOutput = 100 AudioVolumeOutput = 100
SerialPort = /dev/ttyAMA0 SerialPort = /dev/ttyTHS1
SerialBaudRate = 9600 SerialBaudRate = 9600
PanTiltID = 1 PanTiltID = 1
WebUsername = admin WebUsername = admin

View File

@@ -134,8 +134,8 @@
</a> </a>
</div> </div>
<div class="col"> <div class="col">
<a> <a onmousedown="send_stop_movement()">
<i id="btn_center" class="btn-nav-center fa-solid fa-circle"></i> <i id="btn_center" class="btn-nav-center fa-solid fa-circle" title="Stop Movement"></i>
</a> </a>
</div> </div>
<div class="col"> <div class="col">

View File

@@ -692,11 +692,12 @@ function process_command(dx){
* @type {{cpu_temperature: string, ram_usage: string, cpu: string, cpu0: string, cpu1: string, cpu2: string, cpu3: string}} systeminfo * @type {{cpu_temperature: string, ram_usage: string, cpu: string, cpu0: string, cpu1: string, cpu2: string, cpu3: string}} systeminfo
*/ */
let systeminfo = JSON.parse(dx.data); let systeminfo = JSON.parse(dx.data);
//console.log(systeminfo);
if (systeminfo.cpu_temperature && systeminfo.cpu_temperature.length>0) $('#cpu_temperature').html(`${systeminfo.cpu_temperature} °C`); if (systeminfo.cpu_temperature && systeminfo.cpu_temperature.length>0) $('#cpu_temperature').html(`${systeminfo.cpu_temperature} °C`);
if (systeminfo.cpu && systeminfo.cpu.length>0) $('#cpu_usage').html(`${systeminfo.cpu} %`); if (systeminfo.cpu && systeminfo.cpu.length>0) $('#cpu_usage').html(`${systeminfo.cpu} %`);
if (systeminfo.ram_usage && systeminfo.ram_usage.length>0) $('#ram_usage').html(`${systeminfo.ram_usage} %`); if (systeminfo.ram_usage && systeminfo.ram_usage.length>0) $('#ram_usage').html(`${systeminfo.ram_usage} %`);
if (systeminfo.end0_TX && systeminfo.end0_TX.length>0) $('#ethernet_TX').html(systeminfo.end0_TX); if (systeminfo.enP8p1s0_TX && systeminfo.enP8p1s0_TX.length>0) $('#ethernet_TX').html(systeminfo.enP8p1s0_TX);
if (systeminfo.end0_RX && systeminfo.end0_RX.length>0) $('#ethernet_RX').html(systeminfo.end0_RX); if (systeminfo.enP8p1s0_RX && systeminfo.enP8p1s0_RX.length>0) $('#ethernet_RX').html(systeminfo.enP8p1s0_RX);
break; break;
case "GET AUDIOFILES": case "GET AUDIOFILES":
//console.log("Get Audio Files: "+dx.data); //console.log("Get Audio Files: "+dx.data);

View File

@@ -2,17 +2,18 @@
AudioFile01=elangWav.wav AudioFile01=elangWav.wav
AudioFile02=gunshotsWav.wav AudioFile02=gunshotsWav.wav
AudioFile03=pinkNoiseWav.wav AudioFile03=pinkNoiseWav.wav
AudioFile04= AudioFile04=null
AudioFile05=null AudioFile05=null
AudioVolumeOutput=100 AudioVolumeOutput=100
Camera_Rtsp_path=/axis-media/media.amp Camera_Rtsp_path=/axis-media/media.amp
Camera_ip=192.168.10.17 #Camera_Rtsp_path=/video1
Camera_ip=172.17.195.51
Camera_password=password Camera_password=password
Camera_port=80 Camera_port=80
Camera_user=root Camera_user=root
PanTiltID=1 PanTiltID=1
SerialBaudRate=9600 SerialBaudRate=9600
SerialPort=/dev/ttyAMA0 SerialPort=/dev/ttyTHS1
WebHost=0.0.0.0 WebHost=0.0.0.0
WebPassword=bandara WebPassword=bandara
WebPort=8080 WebPort=8080

80
onnx/coco.names Normal file
View File

@@ -0,0 +1,80 @@
person
bicycle
car
motorbike
aeroplane
bus
train
truck
boat
traffic light
fire hydrant
stop sign
parking meter
bench
bird
cat
dog
horse
sheep
cow
elephant
bear
zebra
giraffe
backpack
umbrella
handbag
tie
suitcase
frisbee
skis
snowboard
sports ball
kite
baseball bat
baseball glove
skateboard
surfboard
tennis racket
bottle
wine glass
cup
fork
knife
spoon
bowl
banana
apple
sandwich
orange
broccoli
carrot
hot dog
pizza
donut
cake
chair
sofa
pottedplant
bed
diningtable
toilet
tvmonitor
laptop
mouse
remote
keyboard
cell phone
microwave
oven
toaster
sink
refrigerator
book
clock
vase
scissors
teddy bear
hair drier
toothbrush

BIN
onnx/yolov8n.onnx Normal file

Binary file not shown.

231
pom.xml
View File

@@ -15,195 +15,78 @@
</repository> </repository>
</repositories> </repositories>
<dependencies> <dependencies>
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>javacv</artifactId>
<version>1.5.11</version>
</dependency>
<dependency> <dependency>
<groupId>org.bytedeco</groupId> <groupId>org.bytedeco</groupId>
<artifactId>javacv-platform</artifactId> <artifactId>opencv</artifactId>
<version>1.5.8</version> <version>4.10.0-1.5.11</version>
<exclusions> <classifier>windows-x86_64</classifier>
<exclusion>
<groupId>org.bytedeco</groupId>
<artifactId>leptonica</artifactId>
</exclusion>
<exclusion>
<groupId>org.bytedeco</groupId>
<artifactId>leptonica-platform</artifactId>
</exclusion>
<exclusion>
<groupId>org.bytedeco</groupId>
<artifactId>artoolkitplus</artifactId>
</exclusion>
<exclusion>
<groupId>org.bytedeco</groupId>
<artifactId>artoolkitplus-platform</artifactId>
</exclusion>
<exclusion>
<groupId>org.bytedeco</groupId>
<artifactId>libdc1394</artifactId>
</exclusion>
<exclusion>
<groupId>org.bytedeco</groupId>
<artifactId>libdc1394-platform</artifactId>
</exclusion>
<exclusion>
<groupId>org.bytedeco</groupId>
<artifactId>libfreenect</artifactId>
</exclusion>
<exclusion>
<groupId>org.bytedeco</groupId>
<artifactId>libfreenect-platform</artifactId>
</exclusion>
<exclusion>
<groupId>org.bytedeco</groupId>
<artifactId>libfreenect2</artifactId>
</exclusion>
<exclusion>
<groupId>org.bytedeco</groupId>
<artifactId>libfreenect2-platform</artifactId>
</exclusion>
<exclusion>
<groupId>org.bytedeco</groupId>
<artifactId>flycapture</artifactId>
</exclusion>
<exclusion>
<groupId>org.bytedeco</groupId>
<artifactId>flycapture-platform</artifactId>
</exclusion>
<exclusion>
<groupId>org.bytedeco</groupId>
<artifactId>librealsense</artifactId>
</exclusion>
<exclusion>
<groupId>org.bytedeco</groupId>
<artifactId>librealsense-platform</artifactId>
</exclusion>
<exclusion>
<groupId>org.bytedeco</groupId>
<artifactId>librealsense2</artifactId>
</exclusion>
<exclusion>
<groupId>org.bytedeco</groupId>
<artifactId>librealsense2-platform</artifactId>
</exclusion>
<exclusion>
<groupId>org.bytedeco</groupId>
<artifactId>videoinput</artifactId>
</exclusion>
<exclusion>
<groupId>org.bytedeco</groupId>
<artifactId>videoinput-platform</artifactId>
</exclusion>
<exclusion>
<groupId>org.bytedeco</groupId>
<artifactId>tesseract</artifactId>
</exclusion>
<exclusion>
<groupId>org.bytedeco</groupId>
<artifactId>tesseract-platform</artifactId>
</exclusion>
<!-- platform dibuangin semua, kemudian tambah sendiri linux-arm64, windows-x86_64, linux-x86_64 -->
<exclusion>
<groupId>org.bytedeco</groupId>
<artifactId>javacpp-platform</artifactId>
</exclusion>
<exclusion>
<groupId>org.bytedeco</groupId>
<artifactId>openblas-platform</artifactId>
</exclusion>
<exclusion>
<groupId>org.bytedeco</groupId>
<artifactId>opencv-platform</artifactId>
</exclusion>
<exclusion>
<groupId>org.bytedeco</groupId>
<artifactId>ffmpeg-platform</artifactId>
</exclusion>
<exclusion>
<groupId>org.bytedeco</groupId>
<artifactId>flandmark</artifactId>
</exclusion>
<exclusion>
<groupId>org.bytedeco</groupId>
<artifactId>flandmark-platform</artifactId>
</exclusion>
</exclusions>
</dependency> </dependency>
<!-- manual tambah untuk platform windows-x86_64 -->
<dependency> <dependency>
<groupId>org.bytedeco</groupId> <groupId>org.bytedeco</groupId>
<artifactId>opencv</artifactId> <artifactId>opencv</artifactId>
<version>4.6.0-1.5.8</version> <version>4.10.0-1.5.11</version>
<classifier>windows-x86_64</classifier>
</dependency>
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>javacpp</artifactId>
<version>1.5.8</version>
<classifier>windows-x86_64</classifier>
</dependency>
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>openblas</artifactId>
<version>0.3.21-1.5.8</version>
<classifier>windows-x86_64</classifier>
</dependency>
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>ffmpeg</artifactId>
<version>5.1.2-1.5.8</version>
<classifier>windows-x86_64</classifier>
</dependency>
<!-- manual tambah untuk platform linux-arm64-->
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>opencv</artifactId>
<version>4.6.0-1.5.8</version>
<classifier>linux-arm64</classifier>
</dependency>
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>javacpp</artifactId>
<version>1.5.8</version>
<classifier>linux-arm64</classifier>
</dependency>
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>openblas</artifactId>
<version>0.3.21-1.5.8</version>
<classifier>linux-arm64</classifier> <classifier>linux-arm64</classifier>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.bytedeco</groupId> <groupId>org.bytedeco</groupId>
<artifactId>ffmpeg</artifactId> <artifactId>ffmpeg</artifactId>
<version>5.1.2-1.5.8</version> <version>7.1-1.5.11</version>
<classifier>linux-arm64</classifier> <classifier>windows-x86_64</classifier>
</dependency>
<!-- manual tambah untuk platform linux-x86_64
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>opencv</artifactId>
<version>4.9.0-1.5.10</version>
<classifier>linux-x86_64</classifier>
</dependency>
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>javacpp</artifactId>
<version>1.5.10</version>
<classifier>linux-x86_64</classifier>
</dependency>
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>openblas</artifactId>
<version>0.3.26-1.5.10</version>
<classifier>linux-x86_64</classifier>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.bytedeco</groupId> <groupId>org.bytedeco</groupId>
<artifactId>ffmpeg</artifactId> <artifactId>ffmpeg</artifactId>
<version>6.1.1-1.5.10</version> <version>7.1-1.5.11</version>
<classifier>linux-x86_64</classifier> <classifier>linux-arm64</classifier>
</dependency> </dependency>
--> <dependency>
<groupId>org.bytedeco</groupId>
<artifactId>openblas</artifactId>
<version>0.3.28-1.5.11</version>
<classifier>windows-x86_64</classifier>
</dependency>
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>openblas</artifactId>
<version>0.3.28-1.5.11</version>
<classifier>linux-arm64</classifier>
</dependency>
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>tensorrt</artifactId>
<version>8.6-1.5.10</version>
</dependency>
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>cuda</artifactId>
<version>12.6-9.5-1.5.11</version>
</dependency>
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>javacpp</artifactId>
<version>1.5.11</version>
<classifier>windows-x86_64</classifier>
</dependency>
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>javacpp</artifactId>
<version>1.5.11</version>
<classifier>linux-arm64</classifier>
</dependency>
<dependency> <dependency>
<groupId>com.corundumstudio.socketio</groupId> <groupId>com.corundumstudio.socketio</groupId>
<artifactId>netty-socketio</artifactId> <artifactId>netty-socketio</artifactId>
@@ -212,7 +95,7 @@
<dependency> <dependency>
<groupId>io.javalin</groupId> <groupId>io.javalin</groupId>
<artifactId>javalin</artifactId> <artifactId>javalin</artifactId>
<version> 6.3.0</version> <version> 6.4.0</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>net.java.dev.jna</groupId> <groupId>net.java.dev.jna</groupId>
@@ -227,7 +110,7 @@
<dependency> <dependency>
<groupId>org.projectlombok</groupId> <groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId> <artifactId>lombok</artifactId>
<version>1.18.34</version> <version>1.18.36</version>
<scope>provided</scope> <scope>provided</scope>
</dependency> </dependency>

View File

@@ -1,14 +1,33 @@
package Audio; package Audio;
public class AudioFileProperties { import com.sun.jna.Pointer;
public final int handle; import com.sun.jna.Structure;
public final String filename;
import java.util.Arrays;
import java.util.List;
public class AudioFileProperties extends Structure {
public int handle;
public String filename;
public long Length; public long Length;
public double duration; public double duration;
public AudioFileProperties(int handle, String filename){
public AudioFileProperties(Pointer p){
super(p);
read();
}
public AudioFileProperties(int handle, String filename, long length, double duration){
this.handle = handle; this.handle = handle;
this.filename = filename; this.filename = filename;
this.Length = length;
this.duration = duration;
write();
}
protected List<String> getFieldOrder() {
return Arrays.asList("handle", "filename", "Length", "duration");
} }
} }

View File

@@ -193,9 +193,9 @@ public class AudioPlayer {
int handle = bass.BASS_StreamCreateFile(false, ff.getAbsolutePath(), 0, 0,0); int handle = bass.BASS_StreamCreateFile(false, ff.getAbsolutePath(), 0, 0,0);
if (handle!=0){ if (handle!=0){
Logger.info("Audio file {} opened successfully", ff.getName()); Logger.info("Audio file {} opened successfully", ff.getName());
AudioFileProperties prop = new AudioFileProperties(handle, ff.getName()); long Length = bass.BASS_ChannelGetLength(handle, Bass.BASS_POS_BYTE);
prop.Length = bass.BASS_ChannelGetLength(handle, Bass.BASS_POS_BYTE); double duration = bass.BASS_ChannelBytes2Seconds(handle, Length);
prop.duration = bass.BASS_ChannelBytes2Seconds(handle, prop.Length); AudioFileProperties prop = new AudioFileProperties(handle, ff.getName(), Length, duration);
return prop; return prop;
} else Logger.error("Failed to open audio file {}, Error Code {}", ff.getAbsolutePath(), bass.BASS_ErrorGetCode()); } else Logger.error("Failed to open audio file {}, Error Code {}", ff.getAbsolutePath(), bass.BASS_ErrorGetCode());
} else Logger.info("AudioPlayer not initialized"); } else Logger.info("AudioPlayer not initialized");
@@ -217,8 +217,39 @@ public class AudioPlayer {
} else Logger.info("Audio file {} closed successfully", prop.filename); } else Logger.info("Audio file {} closed successfully", prop.filename);
} else Logger.info("AudioPlayer not initialized"); } else Logger.info("AudioPlayer not initialized");
} }
} }
PlaybackEvent playbackEvent = null;
Bass.SYNCPROC endproc = (handle, channel, data, user)->{
if (user!=null){
AudioFileProperties ap = new AudioFileProperties(user);
if (playbackEvent!=null){
playbackEvent.onPlaybackFinished(ap);
} else Logger.warn("endproc playbackEvent is null");
} else Logger.warn("endproc user is null");
};
Bass.SYNCPROC freeproc = (handle, channel, data, user)->{
if (user!=null){
AudioFileProperties ap = new AudioFileProperties(user);
if (playbackEvent!=null){
playbackEvent.onPlaybackFinished(ap);
} else Logger.warn("freeproc playbackEvent is null");
} else Logger.warn("freeproc user is null");
};
Bass.SYNCPROC failproc = (handle, channel, data, user)->{
if (user!=null){
AudioFileProperties ap = new AudioFileProperties(user);
if (playbackEvent!=null){
playbackEvent.onPlaybackFailure(ap, "Device Failure");
} else Logger.warn("failproc playbackEvent is null");
} else Logger.warn("failproc user is null");
};
/** /**
* Play Audio File * Play Audio File
* @param prop AudioFileProperties object to play * @param prop AudioFileProperties object to play
@@ -226,23 +257,23 @@ public class AudioPlayer {
* @param event PlaybackEvent object to handle playback event * @param event PlaybackEvent object to handle playback event
*/ */
public void PlayAudioFile(AudioFileProperties prop, boolean looping, PlaybackEvent event){ public void PlayAudioFile(AudioFileProperties prop, boolean looping, PlaybackEvent event){
this.playbackEvent = null;
if (inited){ if (inited){
if (prop!=null){ if (prop!=null){
if (bass.BASS_ChannelStart(prop.handle)){ if (bass.BASS_ChannelStart(prop.handle)){
this.playbackEvent = event;
playbackhandle = prop.handle; playbackhandle = prop.handle;
// SyncProcValue spv = new SyncProcValue(prop);
// spv.write();
bass.BASS_ChannelSetAttribute(prop.handle, Bass.BASS_ATTRIB_VOL, playbackvolume); bass.BASS_ChannelSetAttribute(prop.handle, Bass.BASS_ATTRIB_VOL, playbackvolume);
if (looping) bass.BASS_ChannelFlags(prop.handle, Bass.BASS_SAMPLE_LOOP, Bass.BASS_SAMPLE_LOOP); if (looping) bass.BASS_ChannelFlags(prop.handle, Bass.BASS_SAMPLE_LOOP, Bass.BASS_SAMPLE_LOOP);
if (event!=null) event.onPlaybackStart(prop); if (event!=null) event.onPlaybackStart(prop);
int devfailsync = bass.BASS_ChannelSetSync(prop.handle, Bass.BASS_SYNC_DEV_FAIL,0, (handle, channel, data, user)->{ int devfailsync = bass.BASS_ChannelSetSync(prop.handle, Bass.BASS_SYNC_DEV_FAIL,0, failproc, prop.getPointer());
if (event!=null) event.onPlaybackFailure(prop, "Device Failure");
}, null);
if (devfailsync==0) Logger.error("Failed to set Device Failure Sync, Error Code {}", bass.BASS_ErrorGetCode()); if (devfailsync==0) Logger.error("Failed to set Device Failure Sync, Error Code {}", bass.BASS_ErrorGetCode());
int endsync = bass.BASS_ChannelSetSync(prop.handle, Bass.BASS_SYNC_END, 0, (handle, channel, data, user)->{ int endsync = bass.BASS_ChannelSetSync(prop.handle, Bass.BASS_SYNC_END , 0, endproc, prop.getPointer());
if (looping) {
if (event!=null) event.onPlaybackLooped(prop);
} else if (event!=null) event.onPlaybackFinished(prop);
}, null);
if (endsync==0) Logger.error("Failed to set End Sync, Error Code {}", bass.BASS_ErrorGetCode()); if (endsync==0) Logger.error("Failed to set End Sync, Error Code {}", bass.BASS_ErrorGetCode());
int freesync = bass.BASS_ChannelSetSync(prop.handle, Bass.BASS_SYNC_FREE , 0, freeproc, prop.getPointer());
if (freesync==0) Logger.error("Failed to set Free Sync, Error Code {}", bass.BASS_ErrorGetCode());
} else { } else {
if (event!=null) event.onPlaybackFailure(prop, String.format("Failed to play audio file %s, Error Code %d", prop.filename, bass.BASS_ErrorGetCode())); if (event!=null) event.onPlaybackFailure(prop, String.format("Failed to play audio file %s, Error Code %d", prop.filename, bass.BASS_ErrorGetCode()));
} }
@@ -254,4 +285,23 @@ public class AudioPlayer {
} }
} }
// static class SyncProcValue extends Structure{
// public AudioFileProperties ap;
// public SyncProcValue(AudioFileProperties ap){
// this.ap = ap;
// }
//
// public SyncProcValue(Pointer p){
// super(p);
// read();
// }
//
// @Override
// protected List<String> getFieldOrder() {
// return Arrays.asList("ap");
// }
//
//
// }
} }

View File

@@ -2,6 +2,8 @@ package Audio;
import com.sun.jna.*; import com.sun.jna.*;
import java.util.Objects;
@SuppressWarnings("unused") @SuppressWarnings("unused")
public interface Bass extends Library { public interface Bass extends Library {

View File

@@ -0,0 +1,324 @@
package Audio;
import lombok.Getter;
import org.tinylog.Logger;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
public class MultiUSBAudioPlayer {
private final Bass bass;
private int[] deviceid;
@Getter
private boolean inited = false;
PlaybackHandlewithId[] playbackhandle;
float playbackvolume = 1.0f;
List<BassDeviceInfoWithId> playbackdevices = new ArrayList<>();
/**
* Create Multi USB Audio Player
*/
public MultiUSBAudioPlayer() {
bass = Bass.Instance;
Logger.info("Bass Version = {}", Integer.toHexString(bass.BASS_GetVersion()));
}
/**
* Unload Multi USB Audio Player
*/
public void Unload(){
if (inited){
if (deviceid!=null && deviceid.length>0){
for(int id: deviceid){
Logger.info("Freeing Device {}", id);
bass.BASS_SetDevice(id);
bass.BASS_Free();
}
}
}
deviceid = null;
inited = false;
}
/**
* Detect Output Devices
*/
public void DetectOutputDevices(){
Logger.info("Detecting Output Devices...");
int ii = 1;
playbackdevices.clear();
while (true){
Bass.BASS_DEVICEINFO info = new Bass.BASS_DEVICEINFO();
if (bass.BASS_GetDeviceInfo(ii, info)){
//Logger.info("Device {} = {}, flags = {}", ii, info.name, Integer.toHexString(info.flags));
playbackdevices.add(new BassDeviceInfoWithId(ii, info));
ii++;
} else {
break;
}
}
}
/**
* Find playback devices with name
* @param name specific name
* @return array of device id
*/
public int[] FindDeviceIDWithName(String name){
if (playbackdevices!=null && !playbackdevices.isEmpty()){
List<Integer> result = new ArrayList<>();
for(BassDeviceInfoWithId dev : playbackdevices){
if (dev.info.name.toLowerCase().contains(name.toLowerCase())){
Logger.info("Found Device id={}, name={}", dev.id, dev.info.name);
result.add(dev.id);
}
}
return result.stream().mapToInt(i->i).toArray();
}
return new int[0];
}
/**
* Open Devices
* @param device list of device id
* @param freq frequency
* @return true if any device is successfully initialized
*/
public boolean OpenDevice(int[] device, int freq){
if (device!=null && device.length>0){
int flag = Bass.BASS_DEVICE_REINIT | Bass.BASS_DEVICE_16BITS | Bass.BASS_DEVICE_MONO | Bass.BASS_DEVICE_FREQ;
List<Integer> validdevice = new ArrayList<>();
for(int i : device){
boolean result = bass.BASS_Init(i, freq, flag);
if (result){
Logger.info("Device {} initialized", i);
validdevice.add(i);
inited = true;
} else {
Logger.error("Failed to initialize device {}, errorcode={}", i, bass.BASS_ErrorGetCode());
}
}
deviceid = validdevice.stream().mapToInt(i->i).toArray();
return inited;
}
return false;
}
/**
* 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){
if (value<0) value = 0;
if (value>100) value = 100;
if (inited){
if (deviceid!=null && deviceid.length>0){
for(int id : deviceid){
bass.BASS_SetDevice(id);
if (!bass.BASS_SetVolume(value/100.0f)){
Logger.error("Failed to set Master Volume to {}, Error Code {}", value, bass.BASS_ErrorGetCode());
} else Logger.info("Master Volume set to {}", value);
}
} else Logger.error("No device initialized");
} else Logger.info("MultiUSBAudioPlayer not initialized");
}
/**
* Get Playback Volume
* is the volume of the currently playing audio file
* @return 0 - 100
*/
public int getPlaybackvolume(){
if (playbackvolume<0)
return 0;
else if (playbackvolume>1.0f)
return 100;
else
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;
playbackvolume = value/100.0f;
if (playbackhandle!=null && playbackhandle.length>0){
for(PlaybackHandlewithId ph : playbackhandle){
if (ph.handle.handle!=0){
bass.BASS_SetDevice(ph.id);
bass.BASS_ChannelSetAttribute(ph.handle.handle, Bass.BASS_ATTRIB_VOL, playbackvolume);
}
}
}
}
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);
}
/**
* Open Audio File
* @param ff audio file name to open
* @return AudioFileProperties object or null if failed
*/
public PlaybackHandlewithId[] OpenAudioFile(File ff){
if (inited){
AudioFileProperties prop;
List<PlaybackHandlewithId> phs = new ArrayList<>();
for(int id: deviceid){
bass.BASS_SetDevice(id);
int handle = bass.BASS_StreamCreateFile(false, ff.getAbsolutePath(), 0, 0,0);
if (handle!=0){
long Length = bass.BASS_ChannelGetLength(handle, Bass.BASS_POS_BYTE);
double duration = bass.BASS_ChannelBytes2Seconds(handle, Length);
prop = new AudioFileProperties(handle, ff.getName(), Length, duration);
PlaybackHandlewithId ph = new PlaybackHandlewithId(id, prop);
phs.add(ph);
}
}
if (!phs.isEmpty()){
playbackhandle = phs.toArray(new PlaybackHandlewithId[0]);
Logger.info("Audio file {} opened successfully", ff.getName());
return playbackhandle;
} else {
Logger.error("Failed to open audio file {}, Error Code {}", ff.getName(), bass.BASS_ErrorGetCode());
}
} else Logger.info("AudioPlayer not initialized");
return new PlaybackHandlewithId[0];
}
/**
* Close Audio File
* @param prop AudioFileProperties object to close
*/
public void CloseAudioFile(PlaybackHandlewithId[] prop) {
if (inited) {
if (prop != null && prop.length>0) {
for(PlaybackHandlewithId ph : prop){
if (ph.handle.handle!=0){
bass.BASS_SetDevice(ph.id);
if (!bass.BASS_ChannelFree(ph.handle.handle)){
Logger.error("Failed to close audio file {}, Error Code {}", ph.handle.filename, bass.BASS_ErrorGetCode());
} else {
Logger.info("Audio file {} closed successfully", ph.handle.filename);
}
bass.BASS_Stop();
}
}
} else Logger.info("AudioPlayer not initialized");
}
}
PlaybackEvent playbackEvent = null;
Bass.SYNCPROC endproc = (handle, channel, data, user)->{
if (user!=null){
AudioFileProperties ap = new AudioFileProperties(user);
if (playbackEvent!=null){
playbackEvent.onPlaybackFinished(ap);
} else Logger.warn("endproc playbackEvent is null");
} else Logger.warn("endproc user is null");
};
Bass.SYNCPROC freeproc = (handle, channel, data, user)->{
if (user!=null){
AudioFileProperties ap = new AudioFileProperties(user);
if (playbackEvent!=null){
playbackEvent.onPlaybackFinished(ap);
} else Logger.warn("freeproc playbackEvent is null");
} else Logger.warn("freeproc user is null");
};
Bass.SYNCPROC failproc = (handle, channel, data, user)->{
if (user!=null){
AudioFileProperties ap = new AudioFileProperties(user);
if (playbackEvent!=null){
playbackEvent.onPlaybackFailure(ap, "Device Failure");
} else Logger.warn("failproc playbackEvent is null");
} else Logger.warn("failproc user is null");
};
/**
* 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(PlaybackHandlewithId[] prop, boolean looping, PlaybackEvent event){
if (inited){
if (prop!=null && prop.length>0){
this.playbackEvent = event;
for(PlaybackHandlewithId ph : prop){
if (ph.handle.handle!=0){
bass.BASS_SetDevice(ph.id);
bass.BASS_Start();
if (bass.BASS_ChannelStart(ph.handle.handle)) {
bass.BASS_ChannelSetAttribute(ph.handle.handle, Bass.BASS_ATTRIB_VOL, playbackvolume);
if (looping) bass.BASS_ChannelFlags(ph.handle.handle, Bass.BASS_SAMPLE_LOOP, Bass.BASS_SAMPLE_LOOP);
if (event != null) event.onPlaybackStart(ph.handle);
int devfailsync = bass.BASS_ChannelSetSync(ph.handle.handle, Bass.BASS_SYNC_DEV_FAIL, 0, failproc, ph.handle.getPointer());
if (devfailsync == 0) Logger.error("Failed to set Device Failure Sync, Error Code {}", bass.BASS_ErrorGetCode());
int endsync = bass.BASS_ChannelSetSync(ph.handle.handle, Bass.BASS_SYNC_END, 0, endproc, ph.handle.getPointer());
if (endsync == 0) Logger.error("Failed to set End Sync, Error Code {}", bass.BASS_ErrorGetCode());
int freesync = bass.BASS_ChannelSetSync(ph.handle.handle, Bass.BASS_SYNC_FREE, 0, freeproc, ph.handle.getPointer());
if (freesync == 0) Logger.error("Failed to set Free Sync, Error Code {}", bass.BASS_ErrorGetCode());
} else {
if (event != null){
event.onPlaybackFailure(ph.handle, String.format("Failed to play audio file %s, Error Code %d", ph.handle.filename, bass.BASS_ErrorGetCode()));
}
}
}
}
} else {
if (event!=null) event.onPlaybackFailure(null, "AudioFileProperties is null");
}
} else {
if (event!=null) event.onPlaybackFailure(null, "AudioPlayer not initialized");
}
}
public static class PlaybackHandlewithId{
public final int id;
public final AudioFileProperties handle;
public PlaybackHandlewithId(int id, AudioFileProperties handle){
this.id = id;
this.handle = handle;
}
}
static class BassDeviceInfoWithId{
public final int id;
public final Bass.BASS_DEVICEINFO info;
public BassDeviceInfoWithId(int id, Bass.BASS_DEVICEINFO info){
this.id = id;
this.info = info;
}
}
}

View File

@@ -5,10 +5,14 @@ import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Consumer; import java.util.function.Consumer;
import Other.SomeCodes; import Other.SomeCodes;
import id.co.gtc.Main;
import lombok.Getter; import lombok.Getter;
import lombok.Setter; import lombok.Setter;
import org.bytedeco.javacv.Frame; import org.bytedeco.javacv.Frame;
import org.bytedeco.javacv.FrameGrabber; import org.bytedeco.javacv.FrameGrabber;
import org.bytedeco.javacv.OpenCVFrameConverter;
import org.opencv.imgproc.Imgproc;
import org.opencv.core.*;
import org.tinylog.Logger; import org.tinylog.Logger;
public class GrabbingTask implements Runnable { public class GrabbingTask implements Runnable {
@@ -23,6 +27,8 @@ public class GrabbingTask implements Runnable {
@Setter private Consumer<Frame> onLQFrameUpdate; @Setter private Consumer<Frame> onLQFrameUpdate;
@Setter private Consumer<String> onHQBase64Update; @Setter private Consumer<String> onHQBase64Update;
@Setter private Consumer<String> onLQBase64Update; @Setter private Consumer<String> onLQBase64Update;
@Setter private Consumer<Frame> onYoloUpdate;
@Setter private Consumer<String> onYoloBase64Update;
// status of capture fps // status of capture fps
@Getter private int CaptureFPS = 0; @Getter private int CaptureFPS = 0;
@@ -33,6 +39,9 @@ public class GrabbingTask implements Runnable {
// for FPS calculation // for FPS calculation
private int intendedFps = 10; private int intendedFps = 10;
private final YoloDetector_opencv yolo;
@SuppressWarnings("SameParameterValue") @SuppressWarnings("SameParameterValue")
private void updateMessage(String message) { private void updateMessage(String message) {
if (onMessageUpdate != null) { if (onMessageUpdate != null) {
@@ -40,9 +49,17 @@ public class GrabbingTask implements Runnable {
} }
} }
private void updateYoloBase64(String base64) {
if (onYoloBase64Update != null) {
onYoloBase64Update.accept(base64);
}
}
private void updateYoloFrame(Frame frame) {
if (onYoloUpdate != null) {
onYoloUpdate.accept(frame);
}
}
private void updateHQBase64(String base64) { private void updateHQBase64(String base64) {
if (onHQBase64Update != null) { if (onHQBase64Update != null) {
@@ -77,6 +94,9 @@ public class GrabbingTask implements Runnable {
this.isGrabbing = isGrabbing; this.isGrabbing = isGrabbing;
this.grabber = grabber; this.grabber = grabber;
if (fps>0) intendedFps = fps; if (fps>0) intendedFps = fps;
if (Main.use_Yolo) {
yolo = new YoloDetector_opencv();
} else yolo = null;
} }
@@ -84,14 +104,69 @@ public class GrabbingTask implements Runnable {
isGrabbing.set(false); isGrabbing.set(false);
} }
private void processFrame(Frame fr){
if (fr!=null){ @SuppressWarnings({"CallToPrintStackTrace", "CatchMayIgnoreException"})
updateHQFrame(fr); private Mat processFrame(Frame fr){
updateHQBase64(SomeCodes.FrameToBase64(fr)); if (fr!=null && fr.image!=null && fr.imageWidth>0 && fr.imageHeight>0){
Frame resized = SomeCodes.ResizeFrame(fr, lowquality_width, lowquality_height); try(var converter = new OpenCVFrameConverter.ToOrgOpenCvCoreMat()){
updateLQFrame(resized); Mat mat = converter.convert(fr);
updateLQBase64(SomeCodes.FrameToBase64(resized)); if (mat.cols()>0 && mat.rows()>0){
} else updateMessage("processFrame have null frame"); updateHQFrame(fr);
updateHQBase64(SomeCodes.MatToBase64(mat));
Size lowsize = new Size(lowquality_width, lowquality_height);
Mat resized = new Mat();
Imgproc.resize(mat, resized, lowsize);
mat.release();
if (resized.cols()>0 && resized.rows()>0){
Frame resizedFrame = converter.convert(resized);
updateLQFrame(resizedFrame);
updateLQBase64(SomeCodes.MatToBase64(resized));
return resized;
} else Logger.error("processFrame resized size is 0");
} else Logger.error("processFrame Mat size is 0");
} catch (Exception e){
if (SomeCodes.ValidString(e.getMessage())) {
if (!e.getMessage().startsWith("unknown exception")) {
Logger.error("Error processing frame: "+e.getMessage());
e.printStackTrace();
}
}
}
}
// else {
// Logger.warn("processFrame have null frame");
// updateMessage("processFrame have null frame");
// }
return null;
}
private void DetectYolo(Mat mat){
if (yolo!=null){
if (mat!=null && mat.cols()>0 && mat.rows()>0){
try {
// [0] = predict, [1] = mask
Mat[] processed = yolo.Detect(mat);
// gambar dalam bentuk Mat
Mat yolomat = yolo.Process(mat, processed[0], processed[1]);
// convert jadi frame
Frame yoloFrame = SomeCodes.MatToFrame(yolomat);
updateYoloFrame(yoloFrame);
updateYoloBase64(SomeCodes.MatToBase64(yolomat));
} catch (Exception e) {
Logger.error("error processing YOLO, Message : " + e.getMessage());
updateYoloFrame(null);
updateYoloBase64("");
}
} else Logger.error("DetectYolo mat is null");
}
} }
private void flush_grabber(){ private void flush_grabber(){
@@ -102,31 +177,43 @@ public class GrabbingTask implements Runnable {
} }
} }
@SuppressWarnings("CallToPrintStackTrace")
@Override @Override
public void run() { public void run() {
isGrabbing.set(true); isGrabbing.set(true);
Logger.info("Grabbing Task started"); Logger.info("Grabbing Task started");
double fps = grabber.getFrameRate(); double fps = grabber.getFrameRate();
int skippedframes = (int)(fps / intendedFps); int skippedframes = (int)(fps / intendedFps);
//Logger.info("Grabber framerate = {}, intendedFps = {}, Skipping frames = {}", fps, intendedFps, skippedframes); Logger.info("Grabber framerate = {}, intendedFps = {}, Skipping frames = {}", fps, intendedFps, skippedframes);
int framecount = 0; int framecount = 0;
flush_grabber(); flush_grabber();
long starttick = System.currentTimeMillis(); long starttick = System.currentTimeMillis();
while (isGrabbing.get()) { while (isGrabbing.get()) {
try{ try{
Thread.yield(); Thread.yield();
Frame frame = grabber.grab(); Frame frame = grabber.grab();
if (framecount<Integer.MAX_VALUE) framecount++; else framecount = 0; if (framecount<Integer.MAX_VALUE) framecount++; else framecount = 0;
if (framecount % skippedframes == 0) processFrame(frame); Mat resized = processFrame(frame);
// no need to skip frames, just process all frames
if (framecount % skippedframes == 0) {
if (Main.use_Yolo){
DetectYolo(resized);
}
}
resized.release();
} catch (Exception e){ } catch (Exception e){
Logger.error("Error grabbing frame: "+e.getMessage()); Logger.error("Error grabbing frame: "+e.getMessage());
e.printStackTrace();
} }
long elapsed = System.currentTimeMillis() - starttick; long elapsed = System.currentTimeMillis() - starttick;
starttick = System.currentTimeMillis(); starttick = System.currentTimeMillis();
if (elapsed>0) { if (elapsed>0) {
int xx = (int) (1000 / elapsed); int xx = (int) (1000 / elapsed);
if (xx<fps) CaptureFPS = xx; //if (xx<fps) CaptureFPS = xx;
CaptureFPS = xx;
} }
//Logger.info("Elapsed time = {} ms, captureFPS = {}", elapsed, CaptureFPS); //Logger.info("Elapsed time = {} ms, captureFPS = {}", elapsed, CaptureFPS);
} }

View File

@@ -70,10 +70,11 @@ public class PanTiltController {
command[0] = (byte) 0xFF; // add synchronization byte command[0] = (byte) 0xFF; // add synchronization byte
if (isOpen()) { if (isOpen()) {
Main.Max485Direction(true); Main.Max485Direction(true);
serialPort.writeBytes(command, command.length); int written = serialPort.writeBytes(command, command.length);
Main.Max485Direction(false); Main.Max485Direction(false);
Main.Blink_LedPanTilt(); Main.Blink_LedPanTilt();
} Logger.info("Stop movement written {}", written);
} else Logger.warn("Stop Movement failed, serial port not open");
} }
/** /**
@@ -89,10 +90,11 @@ public class PanTiltController {
command[0] = (byte) 0xFF; // add synchronization byte command[0] = (byte) 0xFF; // add synchronization byte
if (isOpen()) { if (isOpen()) {
Main.Max485Direction(true); Main.Max485Direction(true);
serialPort.writeBytes(command, command.length); int written = serialPort.writeBytes(command, command.length);
Main.Max485Direction(false); Main.Max485Direction(false);
Main.Blink_LedPanTilt(); Main.Blink_LedPanTilt();
} Logger.info("Pan Left written {} bytes", written);
} else Logger.warn("Pan Left failed, serial port not open");
} }
/** /**
@@ -108,10 +110,11 @@ public class PanTiltController {
command[0] = (byte) 0xFF; // add synchronization byte command[0] = (byte) 0xFF; // add synchronization byte
if (isOpen()) { if (isOpen()) {
Main.Max485Direction(true); Main.Max485Direction(true);
serialPort.writeBytes(command, command.length); int written = serialPort.writeBytes(command, command.length);
Main.Max485Direction(false); Main.Max485Direction(false);
Main.Blink_LedPanTilt(); Main.Blink_LedPanTilt();
} Logger.info("Pan Right written {} bytes", written);
} else Logger.warn("Pan Right failed, serial port not open");
} }
/** /**
@@ -122,15 +125,16 @@ public class PanTiltController {
if (speed<0) speed = 0; if (speed<0) speed = 0;
if (speed>0x3F) speed = 0x3F; if (speed>0x3F) speed = 0x3F;
byte[] command = new byte[]{0, cameraid, 0, 8, speed, 0, 0}; byte[] command = new byte[]{0, cameraid, 0, 8, 0, speed, 0};
command[6] = Checksum(command); // add checksum command[6] = Checksum(command); // add checksum
command[0] = (byte) 0xFF; // add synchronization byte command[0] = (byte) 0xFF; // add synchronization byte
if (isOpen()) { if (isOpen()) {
Main.Max485Direction(true); Main.Max485Direction(true);
serialPort.writeBytes(command, command.length); int written = serialPort.writeBytes(command, command.length);
Main.Max485Direction(false); Main.Max485Direction(false);
Main.Blink_LedPanTilt(); Main.Blink_LedPanTilt();
} Logger.info("Tilt Up written {} bytes", written);
} else Logger.warn("Tilt Up failed, serial port not open");
} }
/** /**
@@ -141,7 +145,50 @@ public class PanTiltController {
if (speed<0) speed = 0; if (speed<0) speed = 0;
if (speed>0x3F) speed = 0x3F; if (speed>0x3F) speed = 0x3F;
byte[] command = new byte[]{0, cameraid, 0, 16, speed, 0, 0}; byte[] command = new byte[]{0, cameraid, 0, 16, 0, speed, 0};
command[6] = Checksum(command); // add checksum
command[0] = (byte) 0xFF; // add synchronization byte
if (isOpen()) {
Main.Max485Direction(true);
int written = serialPort.writeBytes(command, command.length);
Main.Max485Direction(false);
Main.Blink_LedPanTilt();
Logger.info("Tilt Down written {} bytes", written);
} else Logger.warn("Tilt Down failed, serial port not open");
}
public void DisableMovementTest(){
byte[] command = new byte[]{(byte)0xFF, cameraid, 0, 7, 0, (byte)0x54, (byte)0x5c};
//command[6] = Checksum(command);
//command[0] = (byte) 0xFF;
if (isOpen()) {
Main.Max485Direction(true);
int written = serialPort.writeBytes(command, command.length);
Main.Max485Direction(false);
Main.Blink_LedPanTilt();
Logger.info("DisableMovement test written {} bytes", written);
} else Logger.warn("DisableMovement failed, serial port not open");
}
public void EnableMovementTest(){
byte[] command = new byte[]{(byte)0xFF, cameraid, 0, 3, 0, (byte)0x54, (byte) 0x58};
//command[6] = Checksum(command);
//command[0] = (byte) 0xFF;
if (isOpen()) {
Main.Max485Direction(true);
int written = serialPort.writeBytes(command, command.length);
Main.Max485Direction(false);
Main.Blink_LedPanTilt();
Logger.info("EnableMovement test written {} bytes", written);
} else Logger.warn("EnableMovement failed, serial port not open");
}
/**
* Go to Preset
* @param preset preset number
*/
public void GoToPreset(byte preset){
byte[] command = new byte[]{0, cameraid, 0, 15, preset, 0, 0};
command[6] = Checksum(command); // add checksum command[6] = Checksum(command); // add checksum
command[0] = (byte) 0xFF; // add synchronization byte command[0] = (byte) 0xFF; // add synchronization byte
if (isOpen()) { if (isOpen()) {

View File

@@ -17,8 +17,10 @@ public class RtspGrabber {
private final AtomicBoolean isGrabbing = new AtomicBoolean(false); private final AtomicBoolean isGrabbing = new AtomicBoolean(false);
private Frame lastHQFrame = null; private Frame lastHQFrame = null;
private Frame lastLQFrame = null; private Frame lastLQFrame = null;
private Frame lastYoloFrame = null;
private String lastHQBase64 = null; private String lastHQBase64 = null;
private String lastLQBase64 = null; private String lastLQBase64 = null;
private String lastYoloBase64 = null;
private @Getter int HQWidth = 0; private @Getter int HQWidth = 0;
private @Getter int HQHeight = 0; private @Getter int HQHeight = 0;
private @Getter int LQWidth = 0; private @Getter int LQWidth = 0;
@@ -26,6 +28,7 @@ public class RtspGrabber {
private GrabbingTask grabbingTask; private GrabbingTask grabbingTask;
public RtspGrabber(String ip, String path) { public RtspGrabber(String ip, String path) {
this.rtspUrl = "rtsp://" + ip + path; this.rtspUrl = "rtsp://" + ip + path;
Logger.info("RtspGrabber created with url: " + rtspUrl); Logger.info("RtspGrabber created with url: " + rtspUrl);
} }
@@ -62,6 +65,22 @@ public class RtspGrabber {
return lastLQBase64; return lastLQBase64;
} }
private synchronized void setLastYoloBase64(String base64){
lastYoloBase64 = base64;
}
public synchronized String getLastYoloBase64(){
return lastYoloBase64;
}
private synchronized void setLastYoloFrame(Frame frame){
lastYoloFrame = frame;
}
public synchronized Frame getLastYoloFrame(){
return lastYoloFrame;
}
/** /**
* Start grabbing frames from rtsp * Start grabbing frames from rtsp
* @param useTcp Use tcp instead of udp * @param useTcp Use tcp instead of udp
@@ -143,6 +162,8 @@ public class RtspGrabber {
}); });
tt.setOnHQBase64Update(this::setLastHQBase64); tt.setOnHQBase64Update(this::setLastHQBase64);
tt.setOnLQBase64Update(this::setLastLQBase64); tt.setOnLQBase64Update(this::setLastLQBase64);
tt.setOnYoloUpdate(this::setLastYoloFrame);
tt.setOnYoloBase64Update(this::setLastYoloBase64);
return tt; return tt;
} }
} }

View File

@@ -0,0 +1,169 @@
package Camera;
import lombok.Getter;
import org.bytedeco.ffmpeg.global.avutil;
import org.bytedeco.javacv.FFmpegFrameGrabber;
import org.bytedeco.javacv.Frame;
import org.jetbrains.annotations.NotNull;
import org.tinylog.Logger;
import java.util.concurrent.atomic.AtomicBoolean;
import static Other.SomeCodes.gson;
@SuppressWarnings("unused")
public class RtspGrabber_opencv {
private final String rtspUrl;
private FFmpegFrameGrabber grabber;
private final AtomicBoolean isGrabbing = new AtomicBoolean(false);
private Frame lastHQFrame = null;
private Frame lastLQFrame = null;
private Frame lastYoloFrame = null;
private String lastHQBase64 = null;
private String lastLQBase64 = null;
private String lastYoloBase64 = 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_opencv(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;
}
private synchronized void setLastYoloBase64(String base64){
lastYoloBase64 = base64;
}
public synchronized String getLastYoloBase64(){
return lastYoloBase64;
}
private synchronized void setLastYoloFrame(Frame frame){
lastYoloFrame = frame;
}
public synchronized Frame getLastYoloFrame(){
return lastYoloFrame;
}
/**
* Start grabbing frames from rtsp
* @param useTcp Use tcp instead of udp
*/
public void Start(boolean useTcp, final int width, final int height){
try{
grabber = FFmpegFrameGrabber.createDefault(rtspUrl);
if (useTcp) grabber.setOption("rtsp_transport", "tcp");
grabber.setPixelFormat(avutil.AV_PIX_FMT_BGR24);
grabber.start();
avutil.av_log_set_level(avutil.AV_LOG_ERROR);
Logger.info("Grabber started");
GrabbingTask tt = getGrabbingTask();
grabbingTask = tt;
new Thread(tt).start();
} catch (Exception e){
Logger.error("Error starting grabber: " + e.getMessage());
}
}
/**
* Stop grabbing frames
*/
public void Stop(){
isGrabbing.set(false);
if (grabbingTask!=null){
grabbingTask.Stop();
}
grabbingTask = null;
if (grabber!=null) {
try{
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!=null ? grabbingTask.getCaptureFPS():"0")});
}
public String HQStreamingStatus(){
return gson.toJson(new String[]{String.valueOf(HQWidth), String.valueOf(HQHeight) , String.valueOf(grabbingTask!=null ? grabbingTask.getCaptureFPS(): "0")});
}
@NotNull
private GrabbingTask getGrabbingTask() {
GrabbingTask tt = new GrabbingTask(isGrabbing, grabber,5);
tt.setOnMessageUpdate(Logger::info);
tt.setOnHQFrameUpdate(value -> {
if (value!=null){
if (value.imageWidth>0 && value.imageHeight>0){
setLastHQFrame(value);
HQWidth = value.imageWidth;
HQHeight = value.imageHeight;
}
}
});
tt.setOnLQFrameUpdate(value -> {
if (value!=null){
if (value.imageWidth>0 && value.imageHeight>0){
setLastLQFrame(value);
LQWidth = value.imageWidth;
LQHeight = value.imageHeight;
}
}
});
tt.setOnHQBase64Update(this::setLastHQBase64);
tt.setOnLQBase64Update(this::setLastLQBase64);
tt.setOnYoloUpdate(this::setLastYoloFrame);
tt.setOnYoloBase64Update(this::setLastYoloBase64);
return tt;
}
}

View File

@@ -0,0 +1,169 @@
package Camera;
import Other.SomeCodes;
import id.co.gtc.Main;
import lombok.Getter;
import org.bytedeco.javacpp.DoublePointer;
import org.bytedeco.javacpp.FloatPointer;
import org.bytedeco.javacpp.IntPointer;
import org.bytedeco.opencv.global.opencv_core;
import org.bytedeco.opencv.global.opencv_dnn;
import org.bytedeco.opencv.global.opencv_imgproc;
import org.bytedeco.opencv.opencv_core.*;
import org.bytedeco.opencv.opencv_dnn.Net;
import org.opencv.imgproc.Imgproc;
import org.tinylog.Logger;
import java.io.BufferedReader;
import java.io.FileReader;
import java.util.ArrayList;
import java.util.List;
import static org.bytedeco.opencv.global.opencv_core.CV_32F;
public class YoloDetector {
private Net net;
private @Getter boolean NetLoaded;
private List<String> classes ;
public YoloDetector() {
NetLoaded = false;
net = null;
classes = null;
String namesfile = SomeCodes.ExtractResource("/coco.names", SomeCodes.currentDirectory);
String netfile = SomeCodes.ExtractResource("/yolov8n.onnx", SomeCodes.currentDirectory);
if (SomeCodes.ValidFile(netfile)){
net = opencv_dnn.readNetFromONNX(netfile);
if (Main.haveCuda){
net.setPreferableBackend(opencv_dnn.DNN_BACKEND_CUDA);
net.setPreferableTarget(opencv_dnn.DNN_TARGET_CUDA_FP16);
Logger.info("Net loaded with CUDA");
} else {
net.setPreferableBackend(opencv_dnn.DNN_BACKEND_OPENCV);
net.setPreferableTarget(opencv_dnn.DNN_TARGET_CPU);
Logger.info("Net loaded with CPU");
}
} else Logger.error("net file not found");
if (net!=null){
classes = new ArrayList<>();
if (namesfile!=null){
try(BufferedReader br = new BufferedReader(new FileReader(namesfile))) {
String line;
while ((line = br.readLine()) != null) {
classes.add(line);
}
} catch (Exception e){
Logger.error("reading names file, Exception : ",e.getMessage());
}
}
if (!net.empty()){
if (!classes.isEmpty()){
NetLoaded = true;
} else Logger.error("names file is empty");
} else Logger.error("net is empty");
} else Logger.error("Net is not loaded");
}
// Source : https://blog.csdn.net/taoli188/article/details/134720614
public Mat[] Detect(Mat frame){
try{
if (NetLoaded){
Size inputSize = new Size(640, 640);
Scalar mean = new Scalar(0, 0, 0, 0);
double scaleFactor = 1.0f/255.0f;
boolean swapRB = true;
boolean crop = false;
//Mat blob = opencv_dnn.blobFromImage(frame, scaleFactor, inputSize, mean , swapRB, crop, CV_32F);
Mat blob = new Mat();
opencv_dnn.blobFromImage(frame, blob, scaleFactor, inputSize, mean, swapRB, crop, CV_32F);
net.setInput(blob);
Mat predict = net.forward();
Mat mask = predict.reshape(0,1).reshape(0, predict.size(1));
return new Mat[]{predict,mask};
} else {
Logger.error("Net not loaded");
return new Mat[0];
}
} catch (Exception e){
Logger.error("Error detecting: "+e.getMessage());
return new Mat[0];
}
}
@SuppressWarnings("CallToPrintStackTrace")
public Mat Process(Mat frame, Mat predict, Mat mask){
try{
double width = frame.cols() / 640.0;
double height = frame.rows() / 640.0;
Rect2d[] rect2d = new Rect2d[mask.cols()];
float[] scoref = new float[mask.cols()];
int[] classid = new int[mask.cols()];
for(int i=0;i<mask.cols();i++){
double[] x = SomeCodes.getColumnValues(mask,i, new int[]{0});
double[] y = SomeCodes.getColumnValues(mask,i, new int[]{1});
double[] w = SomeCodes.getColumnValues(mask,i, new int[]{2});
double[] h = SomeCodes.getColumnValues(mask,i, new int[]{3});
rect2d[i] = new Rect2d((x[0]-w[0]/2)*width, (y[0]-h[0]/2)*height, w[0]*width, h[0]*height);
//Mat score = mask.col(i).submat(4, predict.size(1)-1,0,1) ;
Mat score = SomeCodes.getSubmat(mask,i,4,predict.size(1)-1);
// Core.MinMaxLocResult mm = Core.minMaxLoc(score);
// scoref[i] = (float)mm.maxVal;
// classid[i] = (int)mm.maxLoc.y;
DoublePointer minVal = new DoublePointer(1);
DoublePointer maxVal = new DoublePointer(1);
Point minLoc = new Point();
Point maxLoc = new Point();
opencv_core.minMaxLoc(score, minVal, maxVal, minLoc, maxLoc, null);
scoref[i] = (float)maxVal.get();
classid[i] = (int)maxLoc.y();
}
//MatOfRect2d bboxes = new MatOfRect2d(rect2d);
Rect2dVector bboxes = new Rect2dVector(rect2d);
//MatOfFloat scores = new MatOfFloat(scoref);
FloatPointer scores = new FloatPointer(scoref);
//MatOfInt indices = new MatOfInt();
//IntVector indices = new IntVector();
IntPointer indices = new IntPointer();
// minimum confidence for detections
float confidence_threshold = 0.4f;
// Non-maximum suppression threshold
float nms_threshold = 0.4f;
opencv_dnn.NMSBoxes(bboxes, scores, confidence_threshold, nms_threshold, indices);
if (indices.limit()>0){
int[] idx = new int[(int)indices.limit()];
indices.get(idx);
for(int ii : idx){
Rect rr = new Rect(SomeCodes.toPoint(rect2d[ii].tl()), SomeCodes.toSize(rect2d[ii].size()));
opencv_imgproc.rectangle(frame,rr, Scalar.GREEN);
opencv_imgproc.putText(frame, classes.get(classid[ii])+" "+String.format("%.2f", scoref[ii]), rr.tl(), Imgproc.FONT_HERSHEY_SIMPLEX, 1.0, Scalar.RED);
}
}
} catch (Exception e){
Logger.error("Error processing detection: "+e.getMessage());
e.printStackTrace();
}
return frame;
}
}

View File

@@ -0,0 +1,146 @@
package Camera;
import Other.SomeCodes;
import id.co.gtc.Main;
import lombok.Getter;
import org.opencv.core.*;
import org.opencv.dnn.Dnn;
import org.opencv.dnn.Net;
import org.opencv.imgproc.Imgproc;
import org.tinylog.Logger;
import java.io.BufferedReader;
import java.io.FileReader;
import java.util.ArrayList;
import java.util.List;
import static org.bytedeco.opencv.global.opencv_core.CV_32F;
public class YoloDetector_opencv {
private Net net;
private @Getter boolean NetLoaded;
private List<String> classes ;
public YoloDetector_opencv() {
NetLoaded = false;
net = null;
classes = null;
String namesfile = SomeCodes.ExtractResource("/coco.names", SomeCodes.currentDirectory);
String netfile = SomeCodes.ExtractResource("/yolov8n.onnx", SomeCodes.currentDirectory);
if (SomeCodes.ValidFile(netfile)){
net = Dnn.readNetFromONNX(netfile);
if (Main.haveCuda){
net.setPreferableBackend(Dnn.DNN_BACKEND_CUDA);
net.setPreferableTarget(Dnn.DNN_TARGET_CUDA_FP16);
Logger.info("Net loaded with CUDA");
} else {
net.setPreferableBackend(Dnn.DNN_BACKEND_OPENCV);
net.setPreferableTarget(Dnn.DNN_TARGET_CPU);
Logger.info("Net loaded with CPU");
}
} else Logger.error("net file not found");
if (net!=null){
classes = new ArrayList<>();
if (namesfile!=null){
try(BufferedReader br = new BufferedReader(new FileReader(namesfile))) {
String line;
while ((line = br.readLine()) != null) {
classes.add(line);
}
} catch (Exception e){
Logger.error("reading names file, Exception : ",e.getMessage());
}
}
if (!net.empty()){
if (!classes.isEmpty()){
NetLoaded = true;
} else Logger.error("names file is empty");
} else Logger.error("net is empty");
} else Logger.error("Net is not loaded");
}
// Source : https://blog.csdn.net/taoli188/article/details/134720614
public Mat[] Detect(Mat frame){
try{
if (NetLoaded){
Size inputSize = new Size(640, 640);
Scalar mean = new Scalar(0, 0, 0, 0);
float scaleFactor = 1.0f/255.0f;
boolean swapRB = true;
boolean crop = false;
Mat blob = Dnn.blobFromImage(frame, scaleFactor, inputSize, mean , swapRB, crop, CV_32F);
//Mat blob = Dnn.blobFromImage(frame, scaleFactor, inputSize);
net.setInput(blob);
Mat predict = net.forward();
Mat mask = predict.reshape(0,1).reshape(0, predict.size(1));
return new Mat[]{predict,mask};
} else {
Logger.error("Net not loaded");
return new Mat[0];
}
} catch (Exception e){
Logger.error("Error detecting: "+e.getMessage());
return new Mat[0];
}
}
@SuppressWarnings("CallToPrintStackTrace")
public Mat Process(Mat frame, Mat predict, Mat mask){
try{
double width = frame.cols() / 640.0;
double height = frame.rows() / 640.0;
Rect2d[] rect2d = new Rect2d[mask.cols()];
float[] scoref = new float[mask.cols()];
int[] classid = new int[mask.cols()];
for(int i=0;i<mask.cols();i++){
double[] x = mask.col(i).get(0, 0);
double[] y = mask.col(i).get(1, 0);
double[] w = mask.col(i).get(2, 0);
double[] h = mask.col(i).get(3, 0);
rect2d[i] = new Rect2d((x[0]-w[0]/2)*width, (y[0]-h[0]/2)*height, w[0]*width, h[0]*height);
Mat score = mask.col(i).submat(4, predict.size(1)-1,0,1) ;
Core.MinMaxLocResult mm = Core.minMaxLoc(score);
scoref[i] = (float)mm.maxVal;
classid[i] = (int)mm.maxLoc.y;
}
MatOfRect2d bboxes = new MatOfRect2d(rect2d);
MatOfFloat scores = new MatOfFloat(scoref);
MatOfInt indices = new MatOfInt();
// minimum confidence for detections
float confidence_threshold = 0.4f;
// Non-maximum suppression threshold
float nms_threshold = 0.4f;
Dnn.NMSBoxes(bboxes, scores, confidence_threshold, nms_threshold, indices);
if (!indices.empty()){
int[] idx = indices.toArray();
for(int ii : idx){
Rect rr = new Rect(rect2d[ii].tl(), rect2d[ii].size());
Imgproc.rectangle(frame, rr, new Scalar(0, 255, 0), 2);
Imgproc.putText(frame, classes.get(classid[ii])+" "+String.format("%.2f", scoref[ii]), rr.tl(), Imgproc.FONT_HERSHEY_SIMPLEX, 1.0, new Scalar(0, 0, 255));
}
}
} catch (Exception e){
Logger.error("Error processing detection: "+e.getMessage());
e.printStackTrace();
}
return frame;
}
}

View File

@@ -1,45 +1,38 @@
package Other; package Other;
import com.google.gson.Gson; import com.google.gson.Gson;
import org.bytedeco.javacpp.Loader; import com.sun.jna.Platform;
import org.bytedeco.javacpp.BytePointer;
import org.bytedeco.javacpp.indexer.DoubleIndexer;
import org.bytedeco.javacv.Frame; import org.bytedeco.javacv.Frame;
import org.bytedeco.javacv.Java2DFrameConverter;
import org.bytedeco.javacv.OpenCVFrameConverter; import org.bytedeco.javacv.OpenCVFrameConverter;
import org.bytedeco.opencv.global.opencv_core; import org.bytedeco.opencv.global.opencv_core;
import org.bytedeco.opencv.global.opencv_imgcodecs;
import org.bytedeco.opencv.global.opencv_imgproc; import org.bytedeco.opencv.global.opencv_imgproc;
import org.bytedeco.opencv.opencv_core.Mat; import org.bytedeco.opencv.opencv_core.*;
import org.bytedeco.opencv.opencv_core.Size;
import org.bytedeco.opencv.opencv_core.UMat;
import org.bytedeco.opencv.opencv_java;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.opencv.core.MatOfByte; import org.opencv.core.MatOfByte;
import org.opencv.imgcodecs.Imgcodecs; import org.opencv.imgcodecs.Imgcodecs;
import org.tinylog.Logger; import org.tinylog.Logger;
import java.io.*; import java.io.*;
import java.net.Inet4Address;
import java.net.Inet6Address;
import java.net.InetAddress; import java.net.InetAddress;
import java.nio.file.*; import java.nio.file.*;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Base64; import java.util.Base64;
import java.util.Properties; import java.util.Properties;
@SuppressWarnings("unused")
public class SomeCodes { public class SomeCodes {
static{ static{
Loader.load(opencv_java.class); //Loader.load(opencv_java.class);
if (Platform.isLinux()){
LoadLinuxLibrary("/usr/local/lib/libopencv_java4100.so");
} else Logger.info("Platform is not Linux, loading standard opencv");
} }
public final static String currentDirectory = System.getProperty("user.dir"); public final static String currentDirectory = System.getProperty("user.dir");
public final static Path audioPath = Path.of(currentDirectory, "audiofiles"); public final static Path audioPath = Path.of(currentDirectory, "audiofiles");
private static final DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
public static final OpenCVFrameConverter.ToMat matConverter = new OpenCVFrameConverter.ToMat();
public static final OpenCVFrameConverter.ToOrgOpenCvCoreMat CoreMatConverter = new OpenCVFrameConverter.ToOrgOpenCvCoreMat(); public static final OpenCVFrameConverter.ToOrgOpenCvCoreMat CoreMatConverter = new OpenCVFrameConverter.ToOrgOpenCvCoreMat();
public static final Java2DFrameConverter frameConverter = new Java2DFrameConverter();
public static final Path logsPath = Path.of(currentDirectory, "logs");
public static final boolean haveOpenCL = opencv_core.haveOpenCL(); public static final boolean haveOpenCL = opencv_core.haveOpenCL();
public static boolean useOpenCL; public static boolean useOpenCL;
private static final Base64.Encoder base64encoder = java.util.Base64.getEncoder(); private static final Base64.Encoder base64encoder = java.util.Base64.getEncoder();
@@ -48,6 +41,17 @@ public class SomeCodes {
public static final double MB_threshold = 1024.0 * 1024.0; public static final double MB_threshold = 1024.0 * 1024.0;
public static final double GB_threshold = 1024.0 * 1024.0 * 1024.0; public static final double GB_threshold = 1024.0 * 1024.0 * 1024.0;
private static void LoadLinuxLibrary(String library){
if (Platform.isLinux()){
File ff = new File(library);
if (ff.isFile()){
Logger.info("Loading library: "+library);
System.load(ff.getAbsolutePath());
}
}
}
@SuppressWarnings("resource")
public static String[] GetAudioFiles(){ public static String[] GetAudioFiles(){
try{ try{
return Files.list(audioPath).map(f -> f.getFileName().toString()).toArray(String[]::new); return Files.list(audioPath).map(f -> f.getFileName().toString()).toArray(String[]::new);
@@ -58,10 +62,6 @@ public class SomeCodes {
return new String[0]; return new String[0];
} }
public static String LocalDateTimeToString(LocalDateTime x){
return x.format(dtf);
}
public static String ExtractResource(String filename, String targetdirectory){ public static String ExtractResource(String filename, String targetdirectory){
try { try {
File destination = new File(targetdirectory, filename); File destination = new File(targetdirectory, filename);
@@ -89,13 +89,7 @@ public class SomeCodes {
public static boolean ValidDirectory(String path){
if (ValidString(path)){
File ff = new File(path);
return ff.isDirectory();
}
return false;
}
public static boolean ValidFile(String filename){ public static boolean ValidFile(String filename){
if (ValidString(filename)){ if (ValidString(filename)){
@@ -122,6 +116,13 @@ public class SomeCodes {
return defaultspeed; return defaultspeed;
} }
public static boolean ValidIntArray(int[] xx){
if (xx!=null){
return xx.length>0;
}
return false;
}
public static boolean ValidInteger(String x){ public static boolean ValidInteger(String x){
try{ try{
Integer.parseInt(x); Integer.parseInt(x);
@@ -131,6 +132,15 @@ public class SomeCodes {
} }
} }
public static String IntArrayToString(int[] id){
StringBuilder sb = new StringBuilder();
for (int i : id){
if (!sb.isEmpty()) sb.append(",");
sb.append(i);
}
return "["+ sb +"]";
}
public static boolean ValidPortNumber(int port){ public static boolean ValidPortNumber(int port){
return port>0 && port<65536; return port>0 && port<65536;
} }
@@ -144,66 +154,116 @@ public class SomeCodes {
} }
} }
public static boolean ValidIPV4(String ipaddress){ public static String MatToBase64(Mat mat){
if (ValidString(ipaddress)){ if (mat!=null){
try{ if (mat.cols()>0 && mat.rows()>0){
InetAddress inet = InetAddress.getByName(ipaddress); try{
if (inet instanceof Inet4Address){ BytePointer mob = new BytePointer();
if (inet.getHostAddress().equals(ipaddress)){ opencv_imgcodecs.imencode(".jpg", mat, mob);
return true; byte[] data = new byte[(int) mob.limit()];
} mob.get(data);
String base64 = base64encoder.encodeToString(data);
mob.deallocate();
return base64;
} catch (Exception e){
Logger.error("Error converting Mat to Base64: "+e.getMessage());
} }
} catch (Exception ignored) {
}
}
return false;
}
public static boolean ValidIPV6(String ipaddress){
if (ValidString(ipaddress)){
try{
InetAddress inet = InetAddress.getByName(ipaddress);
if (inet instanceof Inet6Address){
if (inet.getHostAddress().equals(ipaddress)){
return true;
}
}
} catch (Exception ignored) {
}
}
return false;
}
public static String GetFileName(String filepath){
if (ValidString(filepath)){
File ff = new File(filepath);
if (ff.isFile()){
return ff.getName();
} }
} }
return ""; return "";
} }
public static String MatToBase64(org.opencv.core.Mat mat){
// Function ini pakai opencv, bukan javacv, jadi perlu Loader.load(opencv_java.class) di awal if (mat!=null){
// lebih optimal untuk konversi frame ke base64 if (mat.cols()>0 && mat.rows()>0){
public static String FrameToBase64(Frame frame){ try{
if (frame!=null){
org.opencv.core.Mat converted = CoreMatConverter.convert(frame);
if (converted!=null){
if (!converted.empty()){
MatOfByte mob = new MatOfByte(); MatOfByte mob = new MatOfByte();
Imgcodecs.imencode(".jpg", converted, mob); Imgcodecs.imencode(".jpg", mat, mob);
byte[] jpgdata = mob.toArray(); String base64 = base64encoder.encodeToString(mob.toArray());
mob.release(); mob.release();
converted.release(); return base64;
return base64encoder.encodeToString(jpgdata); } catch (Exception e){
Logger.error("Error converting Mat to Base64: "+e.getMessage());
} }
} }
} }
return ""; return "";
} }
public static Frame MatToFrame(Mat mat){
if (mat!=null && mat.cols()>0 && mat.rows()>0){
try{
return CoreMatConverter.convert(mat);
} catch (Exception e){
Logger.error("Error converting Mat to Frame: "+e.getMessage());
}
}
return null;
}
public static Frame MatToFrame(org.opencv.core.Mat mat){
if (mat!=null && mat.cols()>0 && mat.rows()>0){
try{
return CoreMatConverter.convert(mat);
} catch (Exception e){
Logger.error("Error converting Mat to Frame: "+e.getMessage());
}
}
return null;
}
public static double[] getColumnValues(Mat mat, int colIndex, int[] rowIndices) {
if (mat.empty()) {
throw new IllegalArgumentException("Mat is empty.");
}
if (colIndex < 0 || colIndex >= mat.cols()) {
throw new IllegalArgumentException("Column index out of range.");
}
// Get the column as a new Mat
Mat colMat = mat.col(colIndex);
// Create an indexer for efficient access
DoubleIndexer indexer = colMat.createIndexer();
// Extract specific row values
double[] values = new double[rowIndices.length];
for (int i = 0; i < rowIndices.length; i++) {
values[i] = indexer.get(rowIndices[i], 0);
}
return values;
}
public static Point toPoint(Point2d p) {
return new Point((int)p.x(), (int)p.y());
}
public static Size toSize(Size2d s) {
return new Size((int)s.width(), (int)s.height());
}
public static Mat getSubmat(Mat mask, int colIndex, int startRow, int endRow) {
if (mask.empty()) {
throw new IllegalArgumentException("Mat is empty.");
}
if (colIndex < 0 || colIndex >= mask.cols()) {
throw new IllegalArgumentException("Column index out of range.");
}
if (startRow < 0 || endRow > mask.rows() || startRow >= endRow) {
throw new IllegalArgumentException("Invalid row range.");
}
// Extract column i
Mat colMat = mask.col(colIndex);
// Extract submatrix from row startRow to endRow
return colMat.rowRange(startRow, endRow);
}
/** /**
* Load properties file * Load properties file
@@ -247,6 +307,7 @@ public class SomeCodes {
return config.getProperty(key, null); return config.getProperty(key, null);
} }
@Deprecated
public static Mat ResizeMat(Mat source, int width, int height){ public static Mat ResizeMat(Mat source, int width, int height){
Size sz = new Size(width, height); Size sz = new Size(width, height);
Mat dest = new Mat(); Mat dest = new Mat();
@@ -254,7 +315,6 @@ public class SomeCodes {
UMat src = new UMat(); UMat src = new UMat();
source.copyTo(src); source.copyTo(src);
UMat dst = new UMat(); UMat dst = new UMat();
opencv_imgproc.resize(src, dst, sz); opencv_imgproc.resize(src, dst, sz);
dst.copyTo(dest); dst.copyTo(dest);
} else { } else {
@@ -263,11 +323,6 @@ public class SomeCodes {
return dest; return dest;
} }
public static Frame ResizeFrame(Frame source, int width, int height){
Mat mat = matConverter.convertToMat(source);
Mat resized = ResizeMat(mat, width, height);
return matConverter.convert(resized);
}
/** /**
* check if an ip address is reachable * check if an ip address is reachable
@@ -283,4 +338,20 @@ public class SomeCodes {
} }
return false; return false;
} }
public static void Sleep(int milliseconds){
try{
Thread.sleep(milliseconds);
} catch (Exception e){
Logger.error("Error sleeping: "+e.getMessage());
}
}
public static GpuMat ConvertToGpuMat(Mat mat){
GpuMat gmat = new GpuMat();
gmat.upload(mat);
return gmat;
}
} }

View File

@@ -32,7 +32,7 @@ public class GPIO {
* @param pin GPIO pin number * @param pin GPIO pin number
* @return true if the pin is already exported * @return true if the pin is already exported
*/ */
public static boolean GpioPinExists(@NotNull RaspberryPi5BPins pin){ public static boolean GpioPinExists(@NotNull JetsonOrinPins pin){
Path pinPath = gpioPath.resolve("gpio"+pin.gpionumber); Path pinPath = gpioPath.resolve("gpio"+pin.gpionumber);
return pinPath.toFile().isDirectory(); return pinPath.toFile().isDirectory();
} }
@@ -42,7 +42,7 @@ public class GPIO {
* @param pin GPIO pin number * @param pin GPIO pin number
* @return true if the pin is successfully exported * @return true if the pin is successfully exported
*/ */
public static boolean ExportPin(@NotNull RaspberryPi5BPins pin){ public static boolean ExportPin(@NotNull JetsonOrinPins pin){
try{ try{
if (Files.isWritable(gpioExportPath)){ if (Files.isWritable(gpioExportPath)){
Files.write(gpioExportPath, String.valueOf(pin.gpionumber).getBytes()); Files.write(gpioExportPath, String.valueOf(pin.gpionumber).getBytes());
@@ -55,12 +55,13 @@ public class GPIO {
return false; return false;
} }
/** /**
* Unexport the pin * Unexport the pin
* @param pin GPIO pin number * @param pin GPIO pin number
* @return true if the pin is successfully unexported * @return true if the pin is successfully unexported
*/ */
public static boolean UnexportPin(@NotNull RaspberryPi5BPins pin){ public static boolean UnexportPin(@NotNull JetsonOrinPins pin){
if (Files.isWritable(gpioUnexportPath)){ if (Files.isWritable(gpioUnexportPath)){
try{ try{
Files.write(gpioUnexportPath, String.valueOf(pin.gpionumber).getBytes()); Files.write(gpioUnexportPath, String.valueOf(pin.gpionumber).getBytes());
@@ -80,7 +81,7 @@ public class GPIO {
* @return "in" if the pin is input, "out" if the pin is output, "unknown" if the direction is unknown * @return "in" if the pin is input, "out" if the pin is output, "unknown" if the direction is unknown
*/ */
@SuppressWarnings("unused") @SuppressWarnings("unused")
public static String GetPinDirection(@NotNull RaspberryPi5BPins pin){ public static String GetPinDirection(@NotNull JetsonOrinPins pin){
Path pinPath = gpioPath.resolve("gpio"+pin.gpionumber).resolve("direction"); Path pinPath = gpioPath.resolve("gpio"+pin.gpionumber).resolve("direction");
if (pinPath.toFile().isFile()){ if (pinPath.toFile().isFile()){
if (Files.isReadable(pinPath)){ if (Files.isReadable(pinPath)){
@@ -100,7 +101,7 @@ public class GPIO {
* @param direction "in" for input, "out" for output * @param direction "in" for input, "out" for output
* @return true if the direction is successfully set * @return true if the direction is successfully set
*/ */
public static boolean SetPinDirection(@NotNull RaspberryPi5BPins pin, String direction){ public static boolean SetPinDirection(@NotNull JetsonOrinPins pin, String direction){
Path pinPath = gpioPath.resolve("gpio"+pin.gpionumber).resolve("direction"); Path pinPath = gpioPath.resolve("gpio"+pin.gpionumber).resolve("direction");
if (pinPath.toFile().isFile()){ if (pinPath.toFile().isFile()){
if (Files.isWritable(pinPath)){ if (Files.isWritable(pinPath)){
@@ -126,7 +127,7 @@ public class GPIO {
* @return true if the value is successfully set * @return true if the value is successfully set
*/ */
@SuppressWarnings("UnusedReturnValue") @SuppressWarnings("UnusedReturnValue")
public static boolean SetValue(@NotNull RaspberryPi5BPins pin, boolean isON){ public static boolean SetValue(@NotNull JetsonOrinPins pin, boolean isON){
Path pinPath = gpioPath.resolve("gpio"+pin.gpionumber).resolve("value"); Path pinPath = gpioPath.resolve("gpio"+pin.gpionumber).resolve("value");
if (pinPath.toFile().isFile()){ if (pinPath.toFile().isFile()){
if (Files.isWritable(pinPath)){ if (Files.isWritable(pinPath)){
@@ -148,7 +149,7 @@ public class GPIO {
* @return "1" if the pin value is 1, "0" if the pin value is 0, "unknown" if the value is unknown * @return "1" if the pin value is 1, "0" if the pin value is 0, "unknown" if the value is unknown
*/ */
@SuppressWarnings("unused") @SuppressWarnings("unused")
public static String GetValue(@NotNull RaspberryPi5BPins pin){ public static String GetValue(@NotNull JetsonOrinPins pin){
Path pinPath = gpioPath.resolve("gpio"+pin.gpionumber).resolve("value"); Path pinPath = gpioPath.resolve("gpio"+pin.gpionumber).resolve("value");
if (pinPath.toFile().isFile()){ if (pinPath.toFile().isFile()){
if (Files.isReadable(pinPath)){ if (Files.isReadable(pinPath)){

View File

@@ -0,0 +1,38 @@
package SBC;
import lombok.Getter;
public class I2C_BUS {
private final Linux_C_lib C = Linux_C_lib.INSTANCE;
private @Getter boolean opened = false;
private final @Getter String i2c_name;
private @Getter int i2c_handle = -1;
public I2C_BUS(int bus_number){
this.i2c_name = "/dev/i2c-"+bus_number;
}
public boolean Open_Bus(){
if (!opened){
final int O_RDWR = 0x00000002;
i2c_handle = C.open(i2c_name, O_RDWR);
if (i2c_handle>=0){
opened = true;
return true;
}
}
return false;
}
public void Close_Bus(){
if (opened){
if (i2c_handle>=0){
C.close(i2c_handle);
i2c_handle = -1;
}
opened = false;
}
}
}

View File

@@ -0,0 +1,147 @@
package SBC;
import lombok.Getter;
@SuppressWarnings("unused")
public class I2C_Device {
Linux_C_lib C = Linux_C_lib.INSTANCE;
private @Getter int bus_handle;
private @Getter int device_address;
private @Getter int dev_handle;
private @Getter boolean opened = false;
/**
* Create I2C Device
* @param bus_handle I2C Bus Handle, from opening I2C_Bus
* @param device_address I2C Device Address
*/
public I2C_Device(int bus_handle, int device_address){
opened = false;
if (bus_handle<0 || device_address<0) return;
this.bus_handle = bus_handle;
this.device_address = device_address;
}
/**
* Open I2C Device in Slave mode
* @return true if successfully opened
*/
public boolean Open_Slave(){
boolean sucess = false;
dev_handle = C.ioctl(bus_handle, I2C_Flags.I2C_SLAVE, device_address);
if (dev_handle>=0){
sucess = true;
}
opened = sucess;
return opened;
}
/**
* Open I2C Device in Slave mode with Force
* @return true if successfully opened
*/
public boolean Open_SlaveForce(){
boolean sucess = false;
dev_handle = C.ioctl(bus_handle, I2C_Flags.I2C_SLAVE_FORCE, device_address);
if (dev_handle>=0){
C.ioctl(bus_handle,I2C_Flags.I2C_RETRIES, 3);
C.ioctl(bus_handle,I2C_Flags.I2C_TIMEOUT, 1000);
sucess = true;
}
opened = sucess;
return opened;
}
/**
* Open I2C Device in Read Write mode
* @return true if successfully opened
*/
public boolean Open_RDWR(){
boolean sucess = false;
dev_handle = C.ioctl(bus_handle, I2C_Flags.I2C_RDWR, device_address);
if (dev_handle>=0){
sucess = true;
}
opened = sucess;
return opened;
}
/**
* Open I2C Device in SMBus mode
* @return true if successfully opened
*/
public boolean Open_SMBus(){
boolean sucess = false;
dev_handle = C.ioctl(bus_handle, I2C_Flags.I2C_SMBUS, device_address);
if (dev_handle>=0){
sucess = true;
}
opened = sucess;
return opened;
}
/**
* Close I2C Device
*/
public void Close(){
C.close(dev_handle);
opened = false;
dev_handle = -1;
}
/**
* Write Bytes to I2C Device
* @param data bytes to write
* @return number of bytes written
*/
public int WriteBytes(byte[] data){
if (bus_handle<0 || dev_handle<0 || device_address<0) return -1;
return C.write(bus_handle, data, data.length);
}
/**
* Write Byte to I2C Device
* @param register_address register address
* @param data byte to write
* @return number of bytes written
*/
public int WriteBytes(int register_address, byte data){
byte[] cmd = new byte[2];
cmd[0] = (byte) register_address;
cmd[1] = data;
return WriteBytes(cmd);
}
/**
* Write Bytes to I2C Device
* @param register_address register address
* @param data bytes to write
* @return number of bytes written
*/
public int WriteBytes(int register_address, byte[] data){
byte[] cmd = new byte[data.length+1];
cmd[0] = (byte) register_address;
System.arraycopy(data, 0, cmd, 1, data.length);
return WriteBytes(cmd);
}
/**
* Read Bytes from I2C Device
* @param readsize number of bytes to read
* @return bytes read
*/
public byte[] ReadBytes(int readsize){
if (bus_handle<0 || dev_handle<0 || device_address<0) return null;
byte[] data = new byte[readsize];
int read = C.read(bus_handle, data, readsize);
if (read<0) return null;
if (read<readsize){
byte[] temp = new byte[read];
System.arraycopy(data, 0, temp, 0, read);
return temp;
}
return data;
}
}

View File

@@ -0,0 +1,13 @@
package SBC;
public class I2C_Flags {
public final static int I2C_RETRIES = 0x701; /* number of times a device address should be polled when not acknowledging */
public final static int I2C_TIMEOUT = 0x702; /* set timeout in units of 10 ms */
public final static int I2C_SLAVE = 0x703; /* Command at ioctl, means : Use this slave address */
public final static int I2C_TENBIT = 0x704; /* 0 for 7 bit addrs, != 0 for 10 bit */
public final static int I2C_FUNCS = 0x705; /* Command at ioctl, means : Get the adapter functionality */
public final static int I2C_SLAVE_FORCE = 0x706; /* Command at ioctl, means : Use this slave address, even if it is already in use by a driver! */
public final static int I2C_RDWR = 0x707; /* Command at ioctl, means : Combined R/W transfer (one stop only) */
public final static int I2C_PEC = 0x708; /* != 0 to use PEC with SMBus */
public final static int I2C_SMBUS = 0x720; /* SMBus transfer */
}

View File

@@ -0,0 +1,38 @@
package SBC;
/**
* Source : <a href="https://jetsonhacks.com/nvidia-jetson-orin-nano-gpio-header-pinout/">...</a>
*/
public enum JetsonOrinPins {
Pin07(7,"AUDIO_MCLK",144),
Pin11(11,"UART1_RTS",112),
Pin12(12,"I2S0_SCLK",50),
Pin13(13,"SPI1_SCK",122),
Pin15(15,"GPIO12",85),
Pin16(16,"SPI1_CS1",126),
Pin18(18,"SPI1_CS0",125),
Pin19(19,"SPI0_MOSI",135),
Pin21(21,"SPI0_MISO",134),
Pin22(22,"SPI1_MISO",123),
Pin23(23,"SPI0_SCK",133),
Pin24(24,"SPI0_CS0",136),
Pin25(26,"SPI0_CS1",137),
Pin29(29,"GPIO01",105),
Pin31(31,"GPIO11",106),
Pin32(32,"GPIO07",41),
Pin33(33,"GPIO13",43),
Pin35(35,"I2S0_FS",53),
Pin36(36,"UART1_CTS",113),
Pin37(37,"SPI1_MOSI",124),
Pin38(38,"I2S0_SDIN",52),
Pin40(40,"I2S0_SDOUT",51);
public final int pin;
public final String name;
public final int gpionumber;
JetsonOrinPins(int pin, String name, int gpionumber){
this.pin = pin;
this.name = name;
this.gpionumber = gpionumber;
}
}

View File

@@ -0,0 +1,20 @@
package SBC;
import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.Pointer;
public interface LibGpioD extends Library {
String CHIP_NAME = "/dev/gpiochip0"; // First GPIO chip
LibGpioD Instance = Native.load("gpiod", LibGpioD.class);
Pointer gpiod_chip_open(String chipname);
void gpiod_chip_close(Pointer chip);
Pointer gpiod_line_get(Pointer chip, int offset);
int gpiod_line_request_output(Pointer line, String consumer, int default_val);
int gpiod_line_request_input(Pointer line, String consumer);
int gpiod_line_set_value(Pointer line, int value);
int gpiod_line_get_value(Pointer line);
void gpiod_line_release(Pointer line);
}

View File

@@ -0,0 +1,69 @@
package SBC;
import java.util.Arrays;
import java.util.List;
import com.sun.jna.Native;
import com.sun.jna.NativeLong;
import com.sun.jna.Pointer;
import com.sun.jna.Structure;
public interface Linux_C_lib extends com.sun.jna.Library {
Linux_C_lib INSTANCE = (Linux_C_lib) Native.load("c", Linux_C_lib.class);
long memcpy(int[] dst, short[] src, long n);
int memcpy(int[] dst, short[] src, int n);
int pipe(int[] fds);
int tcdrain(int fd);
int fcntl(int bus_handle, int command, int args);
int ioctl(int bus_handle, int command, int args);
int ioctl(int bus_handle, int command, int... args);
int ioctl(int bus_handle, int command, Pointer args);
int open(String path, int flags);
int close(int fd);
int write(int bus_handle, byte[] buffer, int count);
int read(int bus_handle, byte[] buffer, int count);
long write(int bus_handle, byte[] buffer, long count);
long read(int bus_handle, byte[] buffer, long count);
int select(int n, int[] read, int[] write, int[] error, timeval timeout);
int poll(int[] fds, int nfds, int timeout);
int tcflush(int fd, int qs);
void perror(String msg);
int tcsendbreak(int fd, int duration);
public class timeval extends Structure {
public NativeLong tv_sec;
public NativeLong tv_usec;
protected List<String> getFieldOrder() {
return Arrays.asList(//
"tv_sec",//
"tv_usec"//
);
}
public timeval(long second, long usecond) {
tv_sec = new NativeLong(second);
tv_usec = new NativeLong(usecond);
}
}
}

View File

@@ -0,0 +1,164 @@
package SBC;
import lombok.Getter;
@SuppressWarnings("unused")
public class PCF8574 extends I2C_Device{
private Byte data = 0;
private final @Getter String[] pinNames = new String[8];
/**
* Create new PCF8574
* @param bus_number I2C Bus Number
* @param address PCF8574 Address
*/
public PCF8574(int bus_number, int address){
super(bus_number, address);
for(int i=0; i<8; i++){
pinNames[i] = i+"";
}
}
/**
* Set new Pin Name
* @param pin pin number, 0-7
* @param name new name
*/
public void setPinName(int pin, String name){
if (pin<0 || pin>7) return;
pinNames[pin] = name;
}
/**
* Get Pin Name
* @param pin pin number, 0-7
* @return pin name, or null if not available
*/
public String getPinName(int pin){
if (pin<0 || pin>7) return null;
return pinNames[pin];
}
/**
* Set All Pins High
* @return true if successful
*/
public boolean AllOn(){
if (super.isOpened()){
if (super.WriteBytes(new byte[]{(byte)0xFF})>0){
data = (byte)0xFF;
return true;
}
}
return false;
}
/**
* Set all Pins Low
* @return true if successful
*/
public boolean AllOff(){
if (super.isOpened()){
if (super.WriteBytes(new byte[]{(byte)0x00})>0){
data = (byte)0x00;
return true;
}
}
return false;
}
/**
* Set Pin by Pin Name
* @param pinName pin name
* @return true if successful
*/
public boolean SetPin(String pinName){
for(int i=0; i<8; i++){
if (pinNames[i].equals(pinName)){
return SetPin(i);
}
}
return false;
}
/**
* Set Pin High
* @param pin pin number 0-7
* @return true if successful
*/
public boolean SetPin(int pin){
if (pin<0 || pin>7) return false;
if (super.isOpened()){
synchronized (data){
data = (byte) (data | (1<<pin));
return super.WriteBytes(new byte[]{data})>0;
}
}
return false;
}
/**
* Clear Pin by Pin Name
* @param pinName pin name
* @return true if successful
*/
public boolean ClearPin(String pinName){
for(int i=0; i<8; i++){
if (pinNames[i].equals(pinName)){
return ClearPin(i);
}
}
return false;
}
/**
* Set Pin Low
* @param pin pin number 0-7
* @return true if successful
*/
public boolean ClearPin(int pin){
if (pin<0 || pin>7) return false;
if (super.isOpened()){
synchronized (data){
data = (byte) (data & ~(1<<pin));
return super.WriteBytes(new byte[]{data})>0;
}
}
return false;
}
/**
* Read Pin by Pin Name
* @param pinName pin name
* @return 1 if high, 0 if low, -1 if error
*/
public int ReadPin(String pinName){
for(int i=0; i<8; i++){
if (pinNames[i].equals(pinName)){
return ReadPin(i);
}
}
return -1;
}
/**
* Read Pin
* @param pin pin to read, 0 - 7
* @return 1 if high, 0 if low, -1 if error
*/
public int ReadPin(int pin){
if (pin<0 || pin>7) return -1;
if (super.isOpened()){
byte[] buffer = super.ReadBytes(1);
byte masker = (byte) (1<<pin);
return (buffer[0] & masker) > 0 ? 1 : 0;
}
return -1;
}
}

View File

@@ -1,42 +0,0 @@
package SBC;
public enum RaspberryPi5BPins {
Pin03(3,"GPIO2/SDA", 573),
Pin05(5,"GPIO3/SCL", 574),
Pin07(7,"GPIO4/GPCLK0", 575),
Pin08(8,"GPIO14/TXD", 585),
Pin10(10,"GPIO15/RXD", 586),
Pin11(11,"GPIO17", 588),
Pin12(12,"GPIO18/PCMCLK", 589),
Pin13(13,"GPIO27", 598),
Pin15(15,"GPIO22", 593),
Pin16(16,"GPIO23", 594),
Pin18(18,"GPIO24", 595),
Pin19(19,"GPIO10/MOSI", 581),
Pin21(21,"GPIO9/MISO", 580),
Pin22(22,"GPIO25", 596),
Pin23(23,"GPIO11/SCLK", 582),
Pin24(24,"GPIO8/CE0", 579),
Pin26(26,"GPIO7/CE1", 578),
Pin27(27,"GPIO0/IDSD", 587),
Pin28(28,"GPIO1/IDSC", 587),
Pin29(29,"GPIO5", 576),
Pin31(31,"GPIO6", 577),
Pin32(32,"GPIO12/PWM0", 583),
Pin33(33,"GPIO13/PWM1", 584),
Pin35(35,"GPIO19/PCMFS", 590),
Pin36(36,"GPIO16", 587),
Pin37(37,"GPIO26", 597),
Pin38(38,"GPIO20/PCMDIN", 591),
Pin40(40,"GPIO21/PCMDOUT", 592);
public final int pin;
public final String name;
public final int gpionumber;
RaspberryPi5BPins(int pin, String name, int gpionumber){
this.pin = pin;
this.name = name;
this.gpionumber = gpionumber;
}
}

View File

@@ -32,7 +32,7 @@ public class SystemInformation {
File ff = new File("/proc/net/dev"); File ff = new File("/proc/net/dev");
if (ff.isFile() && ff.canRead()){ if (ff.isFile() && ff.canRead()){
List<NetworkTransmitReceiveInfo> result = new ArrayList<>(); 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+)"); 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{ try{
String[] lines = Files.readString(ff.toPath()).split("\n"); String[] lines = Files.readString(ff.toPath()).split("\n");
for (String line : lines){ for (String line : lines){

View File

@@ -269,12 +269,14 @@ public class WebServer {
connectedWebsocketClients.clear(); connectedWebsocketClients.clear();
app.stop(); app.stop();
Logger.info("Web server stopped"); Logger.info("Web server stopped");
socketServer.stop();
socketIOClients.forEach((key, client) -> client.disconnect()); socketIOClients.forEach((key, client) -> client.disconnect());
socketIOClients.clear(); socketIOClients.clear();
socketServer.stop();
Logger.info("SocketIO server stopped"); Logger.info("SocketIO server stopped");
} catch (JavalinException e){ } catch (JavalinException e){
Logger.error("Web server failed to stop: {}", e.getMessage()); Logger.error("Web server failed to stop: {}", e.getMessage());
e.printStackTrace();
} }
} }

View File

@@ -1,16 +1,15 @@
package id.co.gtc; package id.co.gtc;
import Audio.AudioFileProperties; import Audio.*;
import Audio.AudioPlayer;
import Audio.Bass;
import Audio.PlaybackEvent;
import Camera.PanTiltController; import Camera.PanTiltController;
import Camera.RtspGrabber; import Camera.RtspGrabber_opencv;
import Camera.VapixProtocol; import Camera.VapixProtocol;
import Other.SomeCodes; import Other.SomeCodes;
import SBC.*; import SBC.*;
import Web.*; import Web.*;
import com.google.gson.JsonObject; import com.google.gson.JsonObject;
import com.sun.jna.Platform;
import com.sun.jna.Pointer;
import org.bytedeco.opencv.global.opencv_core; import org.bytedeco.opencv.global.opencv_core;
import org.tinylog.Logger; import org.tinylog.Logger;
@@ -23,11 +22,21 @@ import java.util.concurrent.Executors;
import static Other.SomeCodes.*; import static Other.SomeCodes.*;
public class Main { public class Main {
//change parameter ini untuk single audio output atau multi audio output
private static final boolean use_multiusb_audio = true;
private static MultiUSBAudioPlayer multiUSBAudioPlayer;
private static MultiUSBAudioPlayer.PlaybackHandlewithId[] playbackHandles;
private static AudioPlayer audioPlayer; private static AudioPlayer audioPlayer;
private static WebServer webServer;
private static RtspGrabber rtspGrabber;
private static PanTiltController panTiltController;
private static AudioFileProperties audioFileProperties; private static AudioFileProperties audioFileProperties;
private static WebServer webServer;
//change parameter ini untuk menggunakan Yolo atau tidak
public static final boolean use_Yolo = false;
private static RtspGrabber_opencv rtspGrabber;
public static boolean haveCuda = false;
private static PanTiltController panTiltController;
private static VapixProtocol vapixProtocol; private static VapixProtocol vapixProtocol;
private static Timer timer; private static Timer timer;
private static int cpuTemperature; private static int cpuTemperature;
@@ -37,24 +46,57 @@ public class Main {
private static NetworkTransmitReceiveInfo[] previousNetworkInfo; private static NetworkTransmitReceiveInfo[] previousNetworkInfo;
private static final Map<String, String> networkTX = new HashMap<>(); private static final Map<String, String> networkTX = new HashMap<>();
private static final Map<String, String> networkRX = new HashMap<>(); private static final Map<String, String> networkRX = new HashMap<>();
private static RaspberryPi5BPins AmplifierPower = null; private static JetsonOrinPins AmplifierPower = null;
private static RaspberryPi5BPins LedWeb = null; private static JetsonOrinPins LedWeb = null;
private static RaspberryPi5BPins LedIpCamera = null; private static JetsonOrinPins LedIpCamera = null;
private static RaspberryPi5BPins LedPanTilt = null; private static JetsonOrinPins LedPanTilt = null;
private static RaspberryPi5BPins Max485Direction = null; private static JetsonOrinPins Max485Direction = null;
private static ExecutorService gpioExecutor = null; private static ExecutorService gpioExecutor = null;
private static PCF8574 pcf8574 = null;
private static final String Version = "V1.09 (17/03/2025)";
// Application start from here // Application start from here
public static void main(String[] args) { public static void main(String[] args) {
System.setProperty("jna.debug_load", "false");
System.out.println("BirdStrikeSoetta "+Version);
Runtime.getRuntime().addShutdownHook(new Thread(() -> { Runtime.getRuntime().addShutdownHook(new Thread(() -> {
if (audioPlayer!=null) audioPlayer.Unload(); if (use_multiusb_audio) {
if (webServer!=null) webServer.Stop(); if (multiUSBAudioPlayer != null) {
if (rtspGrabber!=null) rtspGrabber.Stop(); multiUSBAudioPlayer.Unload();
if (panTiltController!=null) panTiltController.Close(); Logger.info("MultiUSB Audio Unloaded");
if (vapixProtocol!=null) vapixProtocol.Close(); }
if (timer!=null) timer.cancel(); } else {
if (gpioExecutor!=null) gpioExecutor.shutdown(); if (audioPlayer != null) {
audioPlayer.Unload();
Logger.info("Audio Unloaded");
}
}
if (webServer!=null) {
webServer.Stop();
Logger.info("Web Server stopped");
}
if (rtspGrabber!=null) {
rtspGrabber.Stop();
Logger.info("Rtsp Grabber stopped");
}
if (panTiltController!=null) {
panTiltController.Close();
Logger.info("Pan Tilt Controller closed");
}
if (vapixProtocol!=null) {
vapixProtocol.Close();
Logger.info("Vapix Protocol closed");
}
if (timer!=null) {
timer.cancel();
Logger.info("Timer cancelled");
}
if (gpioExecutor!=null) {
gpioExecutor.shutdown();
Logger.info("GPIO Executor shutdown");
}
if (AmplifierPower!=null) { if (AmplifierPower!=null) {
Logger.info("GPIO pin {} unexport : {}",AmplifierPower.pin, GPIO.UnexportPin(AmplifierPower)); Logger.info("GPIO pin {} unexport : {}",AmplifierPower.pin, GPIO.UnexportPin(AmplifierPower));
} }
@@ -70,36 +112,135 @@ public class Main {
if (Max485Direction!=null) { if (Max485Direction!=null) {
Logger.info("GPIO pin {} unexport : {}", Max485Direction.pin, GPIO.UnexportPin(Max485Direction)); Logger.info("GPIO pin {} unexport : {}", Max485Direction.pin, GPIO.UnexportPin(Max485Direction));
} }
if (pcf8574!=null){
pcf8574.Close();
Logger.info("PCF8574 closed");
}
Logger.info("Application Stopped");
})); }));
init_gpio(); Logger.info("Current Directory : "+currentDirectory);
//init_gpio();
init_pcf8574();
init_system_monitoring(); init_system_monitoring();
init_properties(); init_properties();
init_audiofiles(); init_audiofiles();
init_Vapix(); init_Vapix();
init_audio(); if (use_multiusb_audio) {
Logger.info("Using MultiUSB Audio");
init_multiusb_audio();
} else {
Logger.info("Using USB Audio");
init_audio();
}
init_pantiltcontroller(); init_pantiltcontroller();
init_webserver(); init_webserver();
init_rtspgrabber(); init_rtspgrabber();
} }
private static void init_pcf8574(){
if (Platform.isLinux()){
I2C_BUS i2c_bus = new I2C_BUS(7);
if (i2c_bus.Open_Bus()){
Logger.info("I2C Bus opened");
pcf8574 = new PCF8574(i2c_bus.getI2c_handle(), 0x27);
if (pcf8574.Open_Slave()){
Logger.info("PCF8574 opened");
pcf8574.AllOff();
// pcf8574.setPinName(0, "Amplifier Power");
// pcf8574.setPinName(1, "Led Web");
// pcf8574.setPinName(2, "Led IP Camera");
// pcf8574.setPinName(3, "Led Pan Tilt");
// pcf8574.setPinName(4, "Max485 Direction");
gpioExecutor = Executors.newVirtualThreadPerTaskExecutor();
} else {
Logger.error("Failed to open PCF8574");
}
} else {
Logger.error("Failed to open I2C Bus");
}
} else Logger.error("PCF8574 not supported on this platform");
}
// Untuk test libgpiod
// use for jetpack 6.x
@SuppressWarnings("unused")
private static void init_gpio(){ private static void init_gpio(){
if (GPIO.HaveGPIO()){ LibGpioD gpio;
gpioExecutor = Executors.newVirtualThreadPerTaskExecutor(); Pointer openPointer;
AmplifierPower = InitializePin(RaspberryPi5BPins.Pin13, true); // Source : https://jetsonhacks.com/nvidia-jetson-orin-nano-gpio-header-pinout/
LedWeb = InitializePin(RaspberryPi5BPins.Pin15, true); int gpio_MOSI = 135;
LedIpCamera = InitializePin(RaspberryPi5BPins.Pin19, true); int gpio_MISO = 134;
LedPanTilt = InitializePin(RaspberryPi5BPins.Pin21, true); if (Platform.isLinux()){
Max485Direction = InitializePin(RaspberryPi5BPins.Pin23, true); gpio = LibGpioD.Instance;
} openPointer = gpio.gpiod_chip_open(LibGpioD.CHIP_NAME);
if (openPointer!=null){
Logger.info("GPIO Chip opened : {}", LibGpioD.CHIP_NAME);
Pointer miso = gpio.gpiod_line_get(openPointer, gpio_MISO);
if (miso!=null){
Logger.info("GPIO Line MISO opened : {}", gpio_MISO);
if (gpio.gpiod_line_request_input(miso, "MISO")!=0){
Logger.error("Failed to set MISO as input");
} else {
Logger.info("MISO opened");
Logger.info("MISO value : {}", gpio.gpiod_line_get_value(miso));
}
gpio.gpiod_line_release(miso);
Logger.info("GPIO Line MISO released : {}", gpio_MISO);
} else Logger.error("Failed to open GPIO Line : {}", gpio_MISO);
Pointer mosi = gpio.gpiod_line_get(openPointer, gpio_MOSI);
if (mosi!=null){
Logger.info("GPIO Line MOSI opened : {}", gpio_MOSI);
if (gpio.gpiod_line_request_output(mosi, "MOSI", 0)!=0){
Logger.error("Failed to set MOSI as output");
} else {
Logger.info("MOSI opened");
int result = gpio.gpiod_line_set_value(mosi, 1);
if (result!=0){
Logger.error("Failed to set MOSI value : {}", result);
} else Logger.info("Success set MOSI value : 1");
}
gpio.gpiod_line_release(mosi);
Logger.info("GPIO Line MOSI released : {}", gpio_MOSI);
} else Logger.error("Failed to open GPIO Line : {}", gpio_MOSI);
gpio.gpiod_chip_close(openPointer);
Logger.info("GPIO Chip closed : {}", LibGpioD.CHIP_NAME);
} else Logger.error("Failed to open GPIO Chip : {}", LibGpioD.CHIP_NAME);
} else Logger.info("GPIO not supported on this platform");
}
// use for jetpack 4.x and 5.x
@SuppressWarnings("unused")
private static void init_gpio_sysfs(){
if (Platform.isLinux()){
if (GPIO.HaveGPIO()){
gpioExecutor = Executors.newVirtualThreadPerTaskExecutor();
AmplifierPower = InitializePin(JetsonOrinPins.Pin13, true);
LedWeb = InitializePin(JetsonOrinPins.Pin15, true);
LedIpCamera = InitializePin(JetsonOrinPins.Pin19, true);
LedPanTilt = InitializePin(JetsonOrinPins.Pin21, true);
Max485Direction = InitializePin(JetsonOrinPins.Pin23, true);
GPIO.SetValue(AmplifierPower,false);
GPIO.SetValue(LedWeb,false);
GPIO.SetValue(LedIpCamera,false);
GPIO.SetValue(LedPanTilt,false);
GPIO.SetValue(Max485Direction,false);
}
} else Logger.info("GPIO not supported on this platform");
} }
@SuppressWarnings("SameParameterValue") @SuppressWarnings("SameParameterValue")
private static RaspberryPi5BPins InitializePin(RaspberryPi5BPins pin, boolean isOutput){ private static JetsonOrinPins InitializePin(JetsonOrinPins pin, boolean isOutput){
boolean exported = false; boolean exported = false;
if (GPIO.GpioPinExists(pin)){ if (GPIO.GpioPinExists(pin)){
exported = true; exported = true;
@@ -121,29 +262,80 @@ public class Main {
public static void Max485Direction(boolean isTransmit){ public static void Max485Direction(boolean isTransmit){
if (Max485Direction!=null){ if (Max485Direction!=null){
GPIO.SetValue(Max485Direction, isTransmit); GPIO.SetValue(Max485Direction, isTransmit);
} else if (pcf8574!=null && pcf8574.isOpened()){
// if (isTransmit){
// pcf8574.SetPin("Max485 Direction");
// } else {
// pcf8574.ClearPin("Max485 Direction");
// }
} }
} }
// dipanggil di PanTiltController, maka perlu public dan static // dipanggil di PanTiltController, maka perlu public dan static
public static void Blink_LedPanTilt(){ public static void Blink_LedPanTilt(){
Blink(LedPanTilt); if (LedPanTilt!=null){
Blink(LedPanTilt);
} else if (pcf8574!=null && pcf8574.isOpened()){
Blink(1);
}
}
public static void Blink_LedWeb(){
if (LedWeb!=null){
Blink(LedWeb);
} else if (pcf8574!=null && pcf8574.isOpened()){
Blink(3);
}
}
public static void Blink_LedIpCamera(){
if (LedIpCamera!=null){
Blink(LedIpCamera);
} else if (pcf8574!=null && pcf8574.isOpened()){
Blink(2);
}
} }
private static void AmplifierControl(boolean isON){ private static void AmplifierControl(boolean isON){
if (AmplifierPower!=null){ if (AmplifierPower!=null){
Logger.info("GPIO Amplifier Power : ",isON);
GPIO.SetValue(AmplifierPower, isON); GPIO.SetValue(AmplifierPower, isON);
} else if (pcf8574!=null && pcf8574.isOpened()){
if (isON){
Logger.info("PCF8574 Amplifier Power ON");
pcf8574.SetPin(6);
pcf8574.SetPin(5);
pcf8574.SetPin(4);
} else {
Logger.info("PCF8574 Amplifier Power OFF");
pcf8574.ClearPin(6);
pcf8574.ClearPin(5);
pcf8574.ClearPin(4);
}
} }
} }
private static void Blink(RaspberryPi5BPins pin){ private static void Blink(int pin){
if (pcf8574!=null && pcf8574.isOpened()){
if (gpioExecutor!=null){
gpioExecutor.submit(()->{
pcf8574.SetPin(pin);
Sleep(20);
pcf8574.ClearPin(pin);
});
}
}
}
private static void Blink(JetsonOrinPins pin){
if (pin!=null){ if (pin!=null){
if (gpioExecutor!=null){ if (gpioExecutor!=null){
gpioExecutor.submit(()->{ gpioExecutor.submit(()->{
GPIO.SetValue(pin, true); GPIO.SetValue(pin, true);
try { Sleep(20);
Thread.sleep(20);
} catch (InterruptedException ignored) {
}
GPIO.SetValue(pin, false); GPIO.SetValue(pin, false);
}); });
} }
@@ -227,10 +419,16 @@ public class Main {
private static void init_Vapix(){ private static void init_Vapix(){
Properties config = SomeCodes.LoadProperties("config.properties"); Properties config = SomeCodes.LoadProperties("config.properties");
Logger.info("Saved Configuration for Camera");
String ip = config.getProperty("Camera_ip"); String ip = config.getProperty("Camera_ip");
String port = config.getProperty("Camera_port"); String port = config.getProperty("Camera_port");
String username = config.getProperty("Camera_user"); String username = config.getProperty("Camera_user");
String password = config.getProperty("Camera_password"); String password = config.getProperty("Camera_password");
Logger.info("Camera IP : "+ip);
Logger.info("Camera Port : "+port);
Logger.info("Camera Username : "+username);
Logger.info("Camera Password : "+password);
if (ValidString(ip)){ if (ValidString(ip)){
if (ValidPortNumber(port)){ if (ValidPortNumber(port)){
if (ValidString(username)){ if (ValidString(username)){
@@ -246,7 +444,7 @@ public class Main {
} else Logger.error("PTZ Disabled"); } else Logger.error("PTZ Disabled");
Logger.info("Max Zoom: "+vapixProtocol.GetPTZMaxZoom()); Logger.info("Max Zoom: "+vapixProtocol.GetPTZMaxZoom());
Logger.info("Min Zoom: "+vapixProtocol.GetPTZMinZoom()); Logger.info("Min Zoom: "+vapixProtocol.GetPTZMinZoom());
Blink(LedIpCamera); Blink_LedIpCamera();
} else Logger.error("Failed to query camera"); } else Logger.error("Failed to query camera");
} else Logger.error("Camera IP is not reachable"); } else Logger.error("Camera IP is not reachable");
} else Logger.error("Camera Password is not valid string"); } else Logger.error("Camera Password is not valid string");
@@ -255,15 +453,23 @@ public class Main {
} else Logger.error( "Camera IP is not valid string"); } else Logger.error( "Camera IP is not valid string");
} }
private static void init_pantiltcontroller() { private static void init_pantiltcontroller() {
Properties config = SomeCodes.LoadProperties("config.properties"); Properties config = SomeCodes.LoadProperties("config.properties");
String portname = config.getProperty("SerialPort"); String portname = config.getProperty("SerialPort");
String baudrate = config.getProperty("SerialBaudRate"); String baudrate = config.getProperty("SerialBaudRate");
String PanTiltID = config.getProperty("PanTiltID"); String PanTiltID = config.getProperty("PanTiltID");
Logger.info("Saved Configuration for Pan Tilt Controller");
Logger.info("Serial Port : "+portname);
Logger.info("Serial Baud Rate : "+baudrate);
Logger.info("Pan Tilt ID : "+PanTiltID);
if (ValidString(portname)){ if (ValidString(portname)){
if (ValidInteger(baudrate)){ if (ValidInteger(baudrate)){
if (ValidInteger(PanTiltID)){ if (ValidInteger(PanTiltID)){
panTiltController = new PanTiltController(portname, Integer.parseInt(baudrate), Integer.parseInt(PanTiltID)); panTiltController = new PanTiltController(portname, Integer.parseInt(baudrate), Integer.parseInt(PanTiltID));
//if (panTiltController.isOpen()) test_pantiltcontroller();
panTiltController.DisableMovementTest();
} }
} else Logger.error("Invalid PTZ Baudrate"); } else Logger.error("Invalid PTZ Baudrate");
} else Logger.error("Invalid PTZ Port"); } else Logger.error("Invalid PTZ Port");
@@ -274,19 +480,64 @@ public class Main {
// check if really activated // check if really activated
useOpenCL = opencv_core.useOpenCL(); useOpenCL = opencv_core.useOpenCL();
Logger.info("OpenCL available={}, activated={}", haveOpenCL, useOpenCL); Logger.info("OpenCL available={}, activated={}", haveOpenCL, useOpenCL);
haveCuda = opencv_core.getCudaEnabledDeviceCount()>0;
if (haveCuda){
Logger.info("CUDA enabled devices found: " + opencv_core.getCudaEnabledDeviceCount());
//opencv_core.printCudaDeviceInfo(0);
//Logger.info("CUDA enabled : "+opencv_core.useOptimized());
opencv_core.setUseOptimized(true);
Logger.info("CUDA enabled : "+opencv_core.useOptimized());
} else {
Logger.info("No CUDA enabled devices found");
}
// BytePointer buildinfo = opencv_core.getBuildInformation();
// if (buildinfo!=null){
// Logger.info("Opencv build information : {}", buildinfo.getString());
// } else{
// Logger.error("Failed to get OpenCV build information");
// }
Properties config = SomeCodes.LoadProperties("config.properties"); Properties config = SomeCodes.LoadProperties("config.properties");
String targetip = config.getProperty("Camera_ip"); String targetip = config.getProperty("Camera_ip");
String rtsppath = config.getProperty("Camera_Rtsp_path"); String rtsppath = config.getProperty("Camera_Rtsp_path");
int width = 1920;
int height = 1080;
// test pakai sony camera, nanti hapus
// targetip = "172.17.195.51";
// rtsppath = "/video1";
// width = 1280;
// height = 720;
Logger.info("Camera IP: {}, Rtsp Path: {}, Width: {}, Height: {}", targetip, rtsppath, width,height);
rtspGrabber = null; rtspGrabber = null;
if (ValidString(targetip)){ if (ValidString(targetip)){
if (ValidString(rtsppath)){ if (ValidString(rtsppath)){
if (IpIsReachable(targetip)){ if (IpIsReachable(targetip)){
Logger.info("Camera IP is reachable"); Logger.info("Camera IP : "+targetip+" is reachable");
rtspGrabber = new RtspGrabber(targetip, rtsppath); rtspGrabber = new RtspGrabber_opencv(targetip, rtsppath);
rtspGrabber.Start(true, 1920, 1080); rtspGrabber.Start(true, width, height);
} else Logger.error("Camera IP is not reachable"); } else Logger.warn("Camera IP : "+targetip+" is not reachable");
} else Logger.error("Camera Path is not valid string"); } else Logger.warn("Camera Path : "+rtsppath+" is not valid string");
} else Logger.error("Camera IP is not valid string"); } else Logger.warn("Camera IP : "+targetip+" is not valid string");
}
private static void init_multiusb_audio(){
multiUSBAudioPlayer = new MultiUSBAudioPlayer();
multiUSBAudioPlayer.DetectOutputDevices();
int[] devs = multiUSBAudioPlayer.FindDeviceIDWithName("USB");
if (devs!=null && devs.length>0){
Logger.info("MultiUSB Audio Device found : {}", IntArrayToString(devs));
if (multiUSBAudioPlayer.OpenDevice(devs, 48000)){
multiUSBAudioPlayer.setMasterVolume(100);
multiUSBAudioPlayer.setPlaybackvolume(100);
Logger.info("MultiUSB Audio Device ID={} opened", IntArrayToString(devs));
} else Logger.error("Failed to open MultiUSB Audio Device ID={}", IntArrayToString(devs));
} else Logger.error("MultiUSB Audio Device not found");
} }
private static void init_audio() { private static void init_audio() {
@@ -309,16 +560,19 @@ public class Main {
@Override @Override
public void onPlaybackStart(AudioFileProperties prop) { public void onPlaybackStart(AudioFileProperties prop) {
Logger.info("Playback started for {}", prop.filename); Logger.info("Playback started for {}", prop.filename);
AmplifierControl(true);
} }
@Override @Override
public void onPlaybackFinished(AudioFileProperties prop) { public void onPlaybackFinished(AudioFileProperties prop) {
Logger.info("Playback finished for {}", prop.filename); Logger.info("Playback finished for {}", prop.filename);
AmplifierControl(false);
} }
@Override @Override
public void onPlaybackFailure(AudioFileProperties prop, String reason) { public void onPlaybackFailure(AudioFileProperties prop, String reason) {
Logger.error("Playback failed for {}: {}", prop.filename, reason); Logger.error("Playback failed for {}: {}", prop.filename, reason);
AmplifierControl(false);
} }
@Override @Override
@@ -335,36 +589,63 @@ public class Main {
@Override @Override
public WebsocketReply onWebsocketCommand(WebsocketCommand command) { public WebsocketReply onWebsocketCommand(WebsocketCommand command) {
Blink(LedWeb); Blink_LedWeb();
byte speed; byte speed;
String cmd = command.command.toUpperCase().trim(); String cmd = command.command.toUpperCase().trim();
switch (cmd){ switch (cmd){
// Pan Tilt Movement Commands // Pan Tilt Movement Commands
case "PAN LEFT" : case "PAN LEFT" :
Logger.info("PAN LEFT");
speed = GetPanTiltSpeed(command.data, (byte)0x20); speed = GetPanTiltSpeed(command.data, (byte)0x20);
if (panTiltController!=null) panTiltController.PanLeft(speed); if (panTiltController!=null) {
panTiltController.PanLeft(speed);
}
return new WebsocketReply("PAN LEFT", String.valueOf(speed)); return new WebsocketReply("PAN LEFT", String.valueOf(speed));
case "PAN RIGHT" : case "PAN RIGHT" :
Logger.info("PAN RIGHT");
speed = GetPanTiltSpeed(command.data, (byte)0x20); speed = GetPanTiltSpeed(command.data, (byte)0x20);
if (panTiltController!=null) panTiltController.PanRight(speed); if (panTiltController!=null) {
panTiltController.PanRight(speed);
}
return new WebsocketReply("PAN RIGHT", String.valueOf(speed)); return new WebsocketReply("PAN RIGHT", String.valueOf(speed));
case "TILT UP" : case "TILT UP" :
Logger.info("TILT UP");
speed = GetPanTiltSpeed(command.data, (byte)0x20); speed = GetPanTiltSpeed(command.data, (byte)0x20);
if (panTiltController!=null) panTiltController.TiltUp(speed); // kebalik
//if (panTiltController!=null) panTiltController.TiltUp(speed);
if (panTiltController!=null) {
panTiltController.TiltDown(speed);
}
return new WebsocketReply("TILT UP", String.valueOf(speed)); return new WebsocketReply("TILT UP", String.valueOf(speed));
case "TILT DOWN" : case "TILT DOWN" :
Logger.info("TILT DOWN");
speed = GetPanTiltSpeed(command.data, (byte)0x20); speed = GetPanTiltSpeed(command.data, (byte)0x20);
if (panTiltController!=null) panTiltController.TiltDown(speed); // kebalik
//if (panTiltController!=null) panTiltController.TiltDown(speed);
if (panTiltController!=null) {
panTiltController.TiltUp(speed);
}
return new WebsocketReply("TILT DOWN", String.valueOf(speed)); return new WebsocketReply("TILT DOWN", String.valueOf(speed));
case "STOP MOVEMENT" : case "STOP MOVEMENT" :
if (panTiltController!=null) panTiltController.StopMovement(); Logger.info("STOP MOVEMENT");
if (panTiltController!=null) {
panTiltController.StopMovement();
}
return new WebsocketReply("STOP MOVEMENT", ""); return new WebsocketReply("STOP MOVEMENT", "");
// Audio Related Commands // Audio Related Commands
case "MUTE": case "MUTE":
audioPlayer.Mute(); if (use_multiusb_audio){
if (multiUSBAudioPlayer!=null) multiUSBAudioPlayer.Mute();
} else {
if (audioPlayer!=null) audioPlayer.Mute();
}
return new WebsocketReply("MUTE", ""); return new WebsocketReply("MUTE", "");
case "UNMUTE": case "UNMUTE":
audioPlayer.Unmute(); if (use_multiusb_audio){
if (multiUSBAudioPlayer!=null) multiUSBAudioPlayer.Unmute();
} else {
if (audioPlayer!=null) audioPlayer.Unmute();
}
return new WebsocketReply("UNMUTE", ""); return new WebsocketReply("UNMUTE", "");
case "SET VOLUME" : case "SET VOLUME" :
int volume=-1; int volume=-1;
@@ -374,11 +655,20 @@ public class Main {
if (volume>100) volume = 100; if (volume>100) volume = 100;
} }
if (volume>=0){ if (volume>=0){
audioPlayer.setPlaybackvolume(volume); if (use_multiusb_audio){
return new WebsocketReply("SET VOLUME", String.valueOf(volume)); if (multiUSBAudioPlayer!=null) multiUSBAudioPlayer.setPlaybackvolume(volume);
} else{
if (audioPlayer!=null) audioPlayer.setPlaybackvolume(volume);
}
return new WebsocketReply("SET VOLUME", String.valueOf(volume));
} else return new WebsocketReply("SET VOLUME", "Invalid Volume Value"); } else return new WebsocketReply("SET VOLUME", "Invalid Volume Value");
case "GET VOLUME" : case "GET VOLUME" :
int vol = audioPlayer.getPlaybackvolume(); int vol = 0;
if (use_multiusb_audio){
if (multiUSBAudioPlayer!=null) vol = multiUSBAudioPlayer.getPlaybackvolume();
} else {
if (audioPlayer!=null) vol = audioPlayer.getPlaybackvolume();
}
return new WebsocketReply("GET VOLUME", String.valueOf(vol)); return new WebsocketReply("GET VOLUME", String.valueOf(vol));
case "PLAY AUDIO" : case "PLAY AUDIO" :
if (ValidInteger(command.data)){ if (ValidInteger(command.data)){
@@ -387,60 +677,99 @@ public class Main {
if (ValidString(filename)){ if (ValidString(filename)){
File filetoplay = new File(Path.of(currentDirectory, "audiofiles", filename).toString()); File filetoplay = new File(Path.of(currentDirectory, "audiofiles", filename).toString());
if (filetoplay.isFile()){ if (filetoplay.isFile()){
AudioFileProperties afp = audioPlayer.OpenAudioFile(filetoplay); if (use_multiusb_audio){
if (afp!=null){ MultiUSBAudioPlayer.PlaybackHandlewithId[] phs = multiUSBAudioPlayer.OpenAudioFile(filetoplay);
audioFileProperties = afp; if (phs!=null && phs.length>0){
audioPlayer.PlayAudioFile(afp, true, pe); playbackHandles = phs;
AmplifierControl(true); multiUSBAudioPlayer.PlayAudioFile(phs, true, pe);
return new WebsocketReply("PLAY AUDIO", afp.filename); return new WebsocketReply("PLAY AUDIO", filename);
}
return new WebsocketReply("PLAY AUDIO", "Failed to open audio file "+filename);
} else {
AudioFileProperties afp = audioPlayer.OpenAudioFile(filetoplay);
if (afp!=null){
audioFileProperties = afp;
audioPlayer.PlayAudioFile(afp, true, pe);
//AmplifierControl(true);
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", "Failed to open audio file "+filename);
} else return new WebsocketReply("PLAY AUDIO", "Audio file not found : "+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)); } else return new WebsocketReply("PLAY AUDIO", String.format("AudioFile with ID %02d not found", id));
} else return new WebsocketReply("PLAY AUDIO", "Invalid Audio ID"); } else return new WebsocketReply("PLAY AUDIO", "Invalid Audio ID");
case "STOP AUDIO" : case "STOP AUDIO" :
if (audioFileProperties!=null){ if (use_multiusb_audio){
audioPlayer.CloseAudioFile(audioFileProperties); // close previous audio file if (playbackHandles!=null && playbackHandles.length>0){
String filename = audioFileProperties.filename; multiUSBAudioPlayer.CloseAudioFile(playbackHandles);
audioFileProperties = null; String filename = playbackHandles[0].handle.filename;
AmplifierControl(false); playbackHandles = null;
return new WebsocketReply("STOP AUDIO", filename); return new WebsocketReply("STOP AUDIO", filename);
} else return new WebsocketReply("STOP AUDIO", "No audioFileProperties"); } else return new WebsocketReply("STOP AUDIO", "No playbackHandles");
} else {
if (audioFileProperties!=null){
audioPlayer.CloseAudioFile(audioFileProperties); // close previous audio file
String filename = audioFileProperties.filename;
audioFileProperties = null;
//AmplifierControl(false);
return new WebsocketReply("STOP AUDIO", filename);
} else return new WebsocketReply("STOP AUDIO", "No audioFileProperties");
}
// ZOOM Related Commands // ZOOM Related Commands
case "GET MAX ZOOM": case "GET MAX ZOOM":
if (vapixProtocol!=null){ if (vapixProtocol!=null){
Blink(LedIpCamera); Blink_LedIpCamera();
return new WebsocketReply("GET MAX ZOOM", String.valueOf(vapixProtocol.GetPTZMaxZoom())); return new WebsocketReply("GET MAX ZOOM", String.valueOf(vapixProtocol.GetPTZMaxZoom()));
} else return new WebsocketReply("GET MAX ZOOM", "VapixProtocol not initialized"); } else return new WebsocketReply("GET MAX ZOOM", "VapixProtocol not initialized");
case "GET ZOOM": case "GET ZOOM":
if (vapixProtocol!=null){ if (vapixProtocol!=null){
Blink(LedIpCamera); Blink_LedIpCamera();
return new WebsocketReply("GET ZOOM", String.valueOf(vapixProtocol.GetCurrentZoomValue())); return new WebsocketReply("GET ZOOM", String.valueOf(vapixProtocol.GetCurrentZoomValue()));
} else return new WebsocketReply("GET ZOOM", "VapixProtocol not initialized"); } else return new WebsocketReply("GET ZOOM", "VapixProtocol not initialized");
case "SET ZOOM": case "SET ZOOM":
if (vapixProtocol.PTZEnabled()){ if (vapixProtocol!=null){
if (ValidInteger(command.data)){ if (vapixProtocol.PTZEnabled()){
int zoom = Integer.parseInt(command.data); if (ValidInteger(command.data)){
if (zoom<vapixProtocol.GetPTZMinZoom()) zoom = vapixProtocol.GetPTZMinZoom(); int zoom = Integer.parseInt(command.data);
if (zoom>vapixProtocol.GetPTZMaxZoom()) zoom = vapixProtocol.GetPTZMaxZoom(); if (zoom<vapixProtocol.GetPTZMinZoom()) zoom = vapixProtocol.GetPTZMinZoom();
if (vapixProtocol.Zoom(1, zoom)){ if (zoom>vapixProtocol.GetPTZMaxZoom()) zoom = vapixProtocol.GetPTZMaxZoom();
Blink(LedIpCamera); Blink_LedIpCamera();
return new WebsocketReply("ZOOM", String.valueOf(zoom)); if (vapixProtocol.Zoom(1, zoom)){
} else return new WebsocketReply("ZOOM", "Failed to zoom"); return new WebsocketReply("ZOOM", String.valueOf(zoom));
} else return new WebsocketReply("ZOOM", "Invalid Zoom Value"); } else return new WebsocketReply("ZOOM", "Failed to zoom");
} else return new WebsocketReply("ZOOM", "Zoom not supported"); } else return new WebsocketReply("ZOOM", "Invalid Zoom Value");
} else return new WebsocketReply("ZOOM", "Zoom not supported");
}
// Live Streaming Related Commands // Live Streaming Related Commands
case "GET BASE64": case "GET BASE64":
if (rtspGrabber!=null){ if (rtspGrabber!=null){
if (Objects.equals(command.data,"HQ")) if (use_Yolo){
return new WebsocketReply("GET BASE64", "data:image/jpeg;base64,"+ rtspGrabber.getLastHQBase64(), rtspGrabber.HQStreamingStatus()); return switch (command.data) {
else case "HQ" ->
return new WebsocketReply("GET BASE64", "data:image/jpeg;base64,"+ rtspGrabber.getLastLQBase64(), rtspGrabber.LQStreamingStatus()); new WebsocketReply("GET BASE64", "data:image/jpeg;base64," + rtspGrabber.getLastHQBase64(), rtspGrabber.HQStreamingStatus());
case "YOLO" ->
new WebsocketReply("GET BASE64", "data:image/jpeg;base64," + rtspGrabber.getLastLQBase64(), rtspGrabber.LQStreamingStatus());
case "LQ" ->
new WebsocketReply("GET BASE64", "data:image/jpeg;base64," + rtspGrabber.getLastYoloBase64(), rtspGrabber.LQStreamingStatus());
default -> new WebsocketReply("GET BASE64", "RTSP Grabber not initialized");
};
} else {
return switch (command.data) {
case "HQ" ->
new WebsocketReply("GET BASE64", "data:image/jpeg;base64," + rtspGrabber.getLastHQBase64(), rtspGrabber.HQStreamingStatus());
case "LQ" ->
new WebsocketReply("GET BASE64", "data:image/jpeg;base64," + rtspGrabber.getLastLQBase64(), rtspGrabber.LQStreamingStatus());
default -> new WebsocketReply("GET BASE64", "RTSP Grabber not initialized");
};
}
} else return new WebsocketReply("GET BASE64", "RTSP Grabber not initialized"); } else return new WebsocketReply("GET BASE64", "RTSP Grabber not initialized");
case "GET RESOLUTION": case "GET RESOLUTION":
if (vapixProtocol!=null){ if (vapixProtocol!=null){
int[] res = vapixProtocol.GetCurrentResolution(1); int[] res = vapixProtocol.GetCurrentResolution(1);
Blink(LedIpCamera); Blink_LedIpCamera();
return new WebsocketReply("GET RESOLUTION", String.format("%dx%d", res[0], res[1])); return new WebsocketReply("GET RESOLUTION", String.format("%dx%d", res[0], res[1]));
} else return new WebsocketReply("GET RESOLUTION", "VapixProtocol not initialized"); } else return new WebsocketReply("GET RESOLUTION", "VapixProtocol not initialized");
case "GET AUDIOFILES": case "GET AUDIOFILES":