Commit 06/08/2025
This commit is contained in:
1
.idea/misc.xml
generated
1
.idea/misc.xml
generated
@@ -1,4 +1,3 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project version="4">
|
<project version="4">
|
||||||
<component name="ProjectInspectionProfilesVisibleTreeState">
|
<component name="ProjectInspectionProfilesVisibleTreeState">
|
||||||
<entry key="Project Default">
|
<entry key="Project Default">
|
||||||
|
|||||||
16
config.json
Normal file
16
config.json
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
{
|
||||||
|
"ZelloUsername": "gtcdevice01",
|
||||||
|
"ZelloPassword": "GtcDev2025",
|
||||||
|
"ZelloChannel": "GtcDev2025",
|
||||||
|
"ZelloServer": "community",
|
||||||
|
"ZelloWorkNetworkName": "",
|
||||||
|
"ZelloEnterpriseServerDomain": "",
|
||||||
|
"M1": "",
|
||||||
|
"M2": "",
|
||||||
|
"M3": "",
|
||||||
|
"M4": "",
|
||||||
|
"M5": "",
|
||||||
|
"M6": "",
|
||||||
|
"M7": "",
|
||||||
|
"M8": ""
|
||||||
|
}
|
||||||
@@ -9,7 +9,7 @@ $(document).ready(function() {
|
|||||||
$('#indicatorDisconnected').addClass('visually-hidden');
|
$('#indicatorDisconnected').addClass('visually-hidden');
|
||||||
$('#indicatorConnected').removeClass('visually-hidden');
|
$('#indicatorConnected').removeClass('visually-hidden');
|
||||||
setInterval(function() {
|
setInterval(function() {
|
||||||
ws.send(JSON.stringify({ command: "getZelloStatus" }));
|
sendCommand({ command: "getZelloStatus" });
|
||||||
}, 5000);
|
}, 5000);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -39,4 +39,12 @@ $(document).ready(function() {
|
|||||||
ws.onerror = function(error) {
|
ws.onerror = function(error) {
|
||||||
console.error('WebSocket error:', error);
|
console.error('WebSocket error:', error);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function sendCommand(command) {
|
||||||
|
if (ws.readyState === WebSocket.OPEN) {
|
||||||
|
ws.send(JSON.stringify(command));
|
||||||
|
} else {
|
||||||
|
console.error('WebSocket is not open. Unable to send command:', command);
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
@@ -79,7 +79,7 @@ $(document).ready(function() {
|
|||||||
|
|
||||||
function sendCommand(cmd) {
|
function sendCommand(cmd) {
|
||||||
if (ws.readyState === WebSocket.OPEN) {
|
if (ws.readyState === WebSocket.OPEN) {
|
||||||
ws.send(cmd);
|
ws.send(JSON.stringify(cmd));
|
||||||
} else {
|
} else {
|
||||||
console.error('WebSocket is not open. Unable to send command:', JSON.stringify(cmd));
|
console.error('WebSocket is not open. Unable to send command:', JSON.stringify(cmd));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,23 +40,23 @@ $(document).ready(function() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (msg.reply === "getConfig" && msg.data !== undefined ) {
|
if (msg.reply === "getConfig" && msg.data !== undefined ) {
|
||||||
const configData = msg.data;
|
const configData = JSON.parse(msg.data);
|
||||||
console.log('Config Data:', configData);
|
console.log('Config Data:', configData);
|
||||||
$('#zelloUsername').val(configData.ZelloUsername || '');
|
$('#zelloUsername').val(configData.zelloUsername || '');
|
||||||
$('#zelloPassword').val(configData.ZelloPassword || '');
|
$('#zelloPassword').val(configData.zelloPassword || '');
|
||||||
$('#zelloChannel').val(configData.ZelloChannel || '');
|
$('#zelloChannel').val(configData.zelloChannel || '');
|
||||||
if ("community" === configData.ZelloServer) {
|
if ("community" === configData.zelloServer) {
|
||||||
$('#zellocommunity').prop('checked', true);
|
$('#zellocommunity').prop('checked', true);
|
||||||
$('#zelloWorkNetworkName').val('').prop('disabled', true);
|
$('#zelloWorkNetworkName').val('').prop('disabled', true);
|
||||||
$('#zelloEnterpriseServerDomain').val('').prop('disabled', true);
|
$('#zelloEnterpriseServerDomain').val('').prop('disabled', true);
|
||||||
} else if ("work" === configData.ZelloServer) {
|
} else if ("work" === configData.zelloServer) {
|
||||||
$('#zellowork').prop('checked', true);
|
$('#zellowork').prop('checked', true);
|
||||||
$('#zelloWorkNetworkName').val(configData.ZelloWorkNetworkName || '').prop('disabled', false);
|
$('#zelloWorkNetworkName').val(configData.zelloWorkNetworkName || '').prop('disabled', false);
|
||||||
$('#zelloEnterpriseServerDomain').val('').prop('disabled', true);
|
$('#zelloEnterpriseServerDomain').val('').prop('disabled', true);
|
||||||
} else if ("enterprise" === configData.ZelloServer) {
|
} else if ("enterprise" === configData.zelloServer) {
|
||||||
$('#zelloenterprise').prop('checked', true);
|
$('#zelloenterprise').prop('checked', true);
|
||||||
$('#zelloWorkNetworkName').val('').prop('disabled', true);
|
$('#zelloWorkNetworkName').val('').prop('disabled', true);
|
||||||
$('#zelloEnterpriseServerDomain').val(configData.ZelloEnterpriseServerDomain || '').prop('disabled', false);
|
$('#zelloEnterpriseServerDomain').val(configData.zelloEnterpriseServerDomain || '').prop('disabled', false);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (let i = 1; i <= 8; i++) {
|
for (let i = 1; i <= 8; i++) {
|
||||||
@@ -72,8 +72,8 @@ $(document).ready(function() {
|
|||||||
dropdownMenu.append(item);
|
dropdownMenu.append(item);
|
||||||
});
|
});
|
||||||
// Set button text to selected message if present
|
// Set button text to selected message if present
|
||||||
if (configData[`M${i}`]) {
|
if (configData[`m${i}`]) {
|
||||||
dropdownButton.text(configData[`M${i}`]);
|
dropdownButton.text(configData[`m${i}`]);
|
||||||
} else {
|
} else {
|
||||||
dropdownButton.text('');
|
dropdownButton.text('');
|
||||||
}
|
}
|
||||||
@@ -176,7 +176,7 @@ $(document).ready(function() {
|
|||||||
|
|
||||||
function sendCommand(cmd) {
|
function sendCommand(cmd) {
|
||||||
if (ws.readyState === WebSocket.OPEN) {
|
if (ws.readyState === WebSocket.OPEN) {
|
||||||
ws.send(cmd);
|
ws.send(JSON.stringify(cmd));
|
||||||
} else {
|
} else {
|
||||||
console.error('WebSocket is not open. Unable to send command:', JSON.stringify(cmd));
|
console.error('WebSocket is not open. Unable to send command:', JSON.stringify(cmd));
|
||||||
}
|
}
|
||||||
|
|||||||
128
src/Main.kt
128
src/Main.kt
@@ -1,13 +1,28 @@
|
|||||||
|
import audio.AudioFilePlayer
|
||||||
import audio.AudioUtility
|
import audio.AudioUtility
|
||||||
import audio.OpusStreamReceiver
|
import audio.OpusStreamReceiver
|
||||||
|
import com.fasterxml.jackson.core.type.TypeReference
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper
|
||||||
import somecodes.Codes.Companion.ValidString
|
import somecodes.Codes.Companion.ValidString
|
||||||
|
import somecodes.configFile
|
||||||
|
import web.WsReply
|
||||||
import web.webApp
|
import web.webApp
|
||||||
import zello.ZelloClient
|
import zello.ZelloClient
|
||||||
import zello.ZelloEvent
|
import zello.ZelloEvent
|
||||||
|
import javafx.util.Pair
|
||||||
|
import org.slf4j.LoggerFactory
|
||||||
|
import somecodes.Codes.Companion.ValidFile
|
||||||
|
import web.WsCommand
|
||||||
|
import java.util.function.BiFunction
|
||||||
|
|
||||||
//TIP To <b>Run</b> code, press <shortcut actionId="Run"/> or
|
//TIP To <b>Run</b> code, press <shortcut actionId="Run"/> or
|
||||||
// click the <icon src="AllIcons.Actions.Execute"/> icon in the gutter.
|
// click the <icon src="AllIcons.Actions.Execute"/> icon in the gutter.
|
||||||
fun main() {
|
fun main() {
|
||||||
|
val logger = LoggerFactory.getLogger("Main")
|
||||||
|
val objectMapper = ObjectMapper()
|
||||||
|
|
||||||
|
val cfg = configFile()
|
||||||
|
cfg.Load()
|
||||||
val au = AudioUtility()
|
val au = AudioUtility()
|
||||||
var audioID = 0
|
var audioID = 0
|
||||||
val preferedAudioDevice = "Speakers"
|
val preferedAudioDevice = "Speakers"
|
||||||
@@ -23,8 +38,117 @@ fun main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
val o = OpusStreamReceiver(audioID)
|
val o = OpusStreamReceiver(audioID)
|
||||||
|
var afp: AudioFilePlayer? = null
|
||||||
|
|
||||||
val w = webApp("0.0.0.0",3030, javafx.util.Pair("admin","admin1234"))
|
val w = webApp("0.0.0.0",3030, BiFunction {
|
||||||
|
source: String, cmd: WsCommand ->
|
||||||
|
when (source) {
|
||||||
|
"setting" -> when(cmd.command){
|
||||||
|
"getConfig" ->{
|
||||||
|
logger.info("Get Config")
|
||||||
|
WsReply(cmd.command,objectMapper.writeValueAsString(cfg) )
|
||||||
|
}
|
||||||
|
"setZelloConfig" -> {
|
||||||
|
try{
|
||||||
|
val xx = objectMapper.readValue(cmd.data, object: TypeReference<Map<String, String>>() {})
|
||||||
|
cfg.ZelloUsername = xx["ZelloUsername"]
|
||||||
|
cfg.ZelloPassword = xx["ZelloPassword"]
|
||||||
|
cfg.ZelloChannel = xx["ZelloChannel"]
|
||||||
|
cfg.ZelloServer = xx["ZelloServer"]
|
||||||
|
cfg.ZelloWorkNetworkName = xx["ZelloWorkNetworkName"]
|
||||||
|
cfg.ZelloEnterpriseServerDomain = xx["ZelloEnterpriseServerDomain"]
|
||||||
|
|
||||||
|
WsReply(cmd.command,"success")
|
||||||
|
} catch (e: Exception){
|
||||||
|
WsReply(cmd.command,"failed: ${e.message}")
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
"setMessageConfig"-> {
|
||||||
|
try{
|
||||||
|
|
||||||
|
val xx = objectMapper.readValue(cmd.data, object : TypeReference<Map<String, String>>() {})
|
||||||
|
cfg.M1 = xx["M1"]
|
||||||
|
cfg.M2 = xx["M2"]
|
||||||
|
cfg.M3 = xx["M3"]
|
||||||
|
cfg.M4 = xx["M4"]
|
||||||
|
cfg.M5 = xx["M5"]
|
||||||
|
cfg.M6 = xx["M6"]
|
||||||
|
cfg.M7 = xx["M7"]
|
||||||
|
cfg.M8 = xx["M8"]
|
||||||
|
WsReply(cmd.command,"success")
|
||||||
|
} catch (e: Exception){
|
||||||
|
WsReply(cmd.command,"failed: ${e.message}")
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
else -> WsReply(cmd.command,"Invalid command: ${cmd.command}")
|
||||||
|
}
|
||||||
|
|
||||||
|
"prerecordedbroadcast" -> when(cmd.command){
|
||||||
|
"getMessageConfig" ->{
|
||||||
|
val data = mapOf(
|
||||||
|
"M1" to cfg.M1,
|
||||||
|
"M2" to cfg.M2,
|
||||||
|
"M3" to cfg.M3,
|
||||||
|
"M4" to cfg.M4,
|
||||||
|
"M5" to cfg.M5,
|
||||||
|
"M6" to cfg.M6,
|
||||||
|
"M7" to cfg.M7,
|
||||||
|
"M8" to cfg.M8
|
||||||
|
)
|
||||||
|
WsReply(cmd.command, objectMapper.writeValueAsString(data))
|
||||||
|
}
|
||||||
|
"getPlaybackStatus" ->{
|
||||||
|
if (afp!=null && true==afp?.isPlaying){
|
||||||
|
WsReply(cmd.command, "Playing: ${afp?.filename}")
|
||||||
|
} else {
|
||||||
|
WsReply(cmd.command, "Idle")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"playMessage" ->{
|
||||||
|
val filename = when(cmd.data){
|
||||||
|
"M1" -> cfg.M1
|
||||||
|
"M2" -> cfg.M2
|
||||||
|
"M3" -> cfg.M3
|
||||||
|
"M4" -> cfg.M4
|
||||||
|
"M5" -> cfg.M5
|
||||||
|
"M6" -> cfg.M6
|
||||||
|
"M7" -> cfg.M7
|
||||||
|
"M8" -> cfg.M8
|
||||||
|
else -> {
|
||||||
|
null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (ValidFile(filename)){
|
||||||
|
try{
|
||||||
|
val player= AudioFilePlayer(audioID, filename)
|
||||||
|
player.Play { cb -> afp = null}
|
||||||
|
afp = player
|
||||||
|
WsReply(cmd.command,"success")
|
||||||
|
|
||||||
|
} catch (e: Exception){
|
||||||
|
WsReply(cmd.command, "failed: ${e.message}")
|
||||||
|
}
|
||||||
|
} else WsReply(cmd.command,"Invalid file : $filename")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
"stopMessage" ->{
|
||||||
|
afp?.Stop()
|
||||||
|
afp = null
|
||||||
|
WsReply(cmd.command,"success")
|
||||||
|
}
|
||||||
|
else -> WsReply(cmd.command,"Invalid command: ${cmd.command}")
|
||||||
|
}
|
||||||
|
"pocreceiver" -> when(cmd.command){
|
||||||
|
else -> WsReply(cmd.command,"Invalid command: ${cmd.command}")
|
||||||
|
}
|
||||||
|
else -> WsReply(cmd.command,"Invalid source: $source")
|
||||||
|
}
|
||||||
|
|
||||||
|
} , Pair("admin","admin1234"))
|
||||||
w.Start()
|
w.Start()
|
||||||
|
|
||||||
val z = ZelloClient.fromConsumerZello("gtcdevice01","GtcDev2025")
|
val z = ZelloClient.fromConsumerZello("gtcdevice01","GtcDev2025")
|
||||||
@@ -98,3 +222,5 @@ fun main() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -7,9 +7,10 @@ import java.util.function.Consumer
|
|||||||
* Supported extensions : .wav, .mp3
|
* Supported extensions : .wav, .mp3
|
||||||
*/
|
*/
|
||||||
@Suppress("unused")
|
@Suppress("unused")
|
||||||
class AudioFilePlayer(deviceID: Int, val filename: String, device_samplingrate: Int = 48000) {
|
class AudioFilePlayer(deviceID: Int, val filename: String?, device_samplingrate: Int = 48000) {
|
||||||
val bass: Bass = Bass.Instance
|
val bass: Bass = Bass.Instance
|
||||||
var filehandle = 0
|
var filehandle = 0
|
||||||
|
var isPlaying = false
|
||||||
init{
|
init{
|
||||||
if (bass.BASS_SetDevice(deviceID)){
|
if (bass.BASS_SetDevice(deviceID)){
|
||||||
filehandle = bass.BASS_StreamCreateFile(false, filename, 0, 0, 0)
|
filehandle = bass.BASS_StreamCreateFile(false, filename, 0, 0, 0)
|
||||||
@@ -19,17 +20,30 @@ class AudioFilePlayer(deviceID: Int, val filename: String, device_samplingrate:
|
|||||||
} else throw Exception("Failed to set device $deviceID")
|
} else throw Exception("Failed to set device $deviceID")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun Stop(){
|
||||||
|
if (filehandle!=0){
|
||||||
|
bass.BASS_ChannelStop(filehandle)
|
||||||
|
bass.BASS_StreamFree(filehandle)
|
||||||
|
filehandle = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun Play(finished: Consumer<Any> ) : Boolean{
|
fun Play(finished: Consumer<Any> ) : Boolean{
|
||||||
if (bass.BASS_ChannelPlay(filehandle, false)){
|
if (bass.BASS_ChannelPlay(filehandle, false)){
|
||||||
|
|
||||||
val thread = Thread{
|
val thread = Thread{
|
||||||
|
isPlaying = true
|
||||||
while(true){
|
while(true){
|
||||||
Thread.sleep(1000)
|
Thread.sleep(1000)
|
||||||
|
|
||||||
if (bass.BASS_ChannelIsActive(filehandle)!= Bass.BASS_ACTIVE_PLAYING){
|
if (bass.BASS_ChannelIsActive(filehandle)!= Bass.BASS_ACTIVE_PLAYING){
|
||||||
// finished playing
|
// finished playing
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
isPlaying = false
|
||||||
|
bass.BASS_StreamFree(filehandle)
|
||||||
|
filehandle = 0
|
||||||
finished.accept(true)
|
finished.accept(true)
|
||||||
}
|
}
|
||||||
thread.name = "AudioFilePlayer $filename"
|
thread.name = "AudioFilePlayer $filename"
|
||||||
|
|||||||
@@ -1,9 +1,23 @@
|
|||||||
package somecodes
|
package somecodes
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
@Suppress("unused")
|
@Suppress("unused")
|
||||||
class Codes {
|
class Codes {
|
||||||
|
private val objectMapper = ObjectMapper()
|
||||||
companion object{
|
companion object{
|
||||||
|
|
||||||
|
fun ValidFile(s: String?) : Boolean {
|
||||||
|
if (s!=null){
|
||||||
|
if (ValidString(s)){
|
||||||
|
val ff = File(s)
|
||||||
|
return ff.isFile
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
fun ValidString(s : String?) : Boolean {
|
fun ValidString(s : String?) : Boolean {
|
||||||
return s != null && s.isNotEmpty() && s.isNotBlank()
|
return s != null && s.isNotEmpty() && s.isNotBlank()
|
||||||
}
|
}
|
||||||
|
|||||||
96
src/somecodes/configFile.kt
Normal file
96
src/somecodes/configFile.kt
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
package somecodes
|
||||||
|
|
||||||
|
import java.nio.file.Path
|
||||||
|
import kotlin.io.path.Path
|
||||||
|
|
||||||
|
class configFile {
|
||||||
|
var ZelloUsername: String? = "gtcdevice01"
|
||||||
|
var ZelloPassword: String? = "GtcDev2025"
|
||||||
|
var ZelloChannel: String? = "GtcDev2025"
|
||||||
|
var ZelloServer: String? = "community"
|
||||||
|
var ZelloWorkNetworkName: String? = ""
|
||||||
|
var ZelloEnterpriseServerDomain: String? = ""
|
||||||
|
var M1: String? = ""
|
||||||
|
var M2: String? = ""
|
||||||
|
var M3: String? = ""
|
||||||
|
var M4: String? = ""
|
||||||
|
var M5: String? = ""
|
||||||
|
var M6: String? = ""
|
||||||
|
var M7: String? = ""
|
||||||
|
var M8: String? = ""
|
||||||
|
|
||||||
|
private val filepath : Path = Path(System.getProperty("user.dir"), "config.json")
|
||||||
|
|
||||||
|
fun Load(){
|
||||||
|
if (filepath.toFile().exists()){
|
||||||
|
// file found, then load the configuration to configFile object
|
||||||
|
try{
|
||||||
|
val json = filepath.toFile().readText()
|
||||||
|
val configMap = json.split(",").associate { it ->
|
||||||
|
val (key, value) = it.split(":").map { it.trim().removeSurrounding("\"") }
|
||||||
|
key to value
|
||||||
|
}
|
||||||
|
|
||||||
|
ZelloUsername = configMap["ZelloUsername"]
|
||||||
|
ZelloPassword = configMap["ZelloPassword"]
|
||||||
|
ZelloChannel = configMap["ZelloChannel"]
|
||||||
|
ZelloServer = configMap["ZelloServer"]
|
||||||
|
ZelloWorkNetworkName = configMap["ZelloWorkNetworkName"]
|
||||||
|
ZelloEnterpriseServerDomain = configMap["ZelloEnterpriseServerDomain"]
|
||||||
|
M1 = configMap["M1"]
|
||||||
|
M2 = configMap["M2"]
|
||||||
|
M3 = configMap["M3"]
|
||||||
|
M4 = configMap["M4"]
|
||||||
|
M5 = configMap["M5"]
|
||||||
|
M6 = configMap["M6"]
|
||||||
|
M7 = configMap["M7"]
|
||||||
|
M8 = configMap["M8"]
|
||||||
|
} catch (e: Exception) {
|
||||||
|
println("Error loading configuration: ${e.message}")
|
||||||
|
}
|
||||||
|
} else CreateDefaultConfig()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun CreateDefaultConfig() {
|
||||||
|
ZelloUsername = "gtcdevice01"
|
||||||
|
ZelloPassword = "GtcDev2025"
|
||||||
|
ZelloChannel = "GtcDev2025"
|
||||||
|
ZelloServer = "community"
|
||||||
|
ZelloWorkNetworkName = ""
|
||||||
|
ZelloEnterpriseServerDomain = ""
|
||||||
|
M1 = ""
|
||||||
|
M2 = ""
|
||||||
|
M3 = ""
|
||||||
|
M4 = ""
|
||||||
|
M5 = ""
|
||||||
|
M6 = ""
|
||||||
|
M7 = ""
|
||||||
|
M8 = ""
|
||||||
|
Save()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Save(){
|
||||||
|
try {
|
||||||
|
// Convert the configFile object to JSON and write it to the file
|
||||||
|
val json = """{
|
||||||
|
"ZelloUsername": "$ZelloUsername",
|
||||||
|
"ZelloPassword": "$ZelloPassword",
|
||||||
|
"ZelloChannel": "$ZelloChannel",
|
||||||
|
"ZelloServer": "$ZelloServer",
|
||||||
|
"ZelloWorkNetworkName": "$ZelloWorkNetworkName",
|
||||||
|
"ZelloEnterpriseServerDomain": "$ZelloEnterpriseServerDomain",
|
||||||
|
"M1": "$M1",
|
||||||
|
"M2": "$M2",
|
||||||
|
"M3": "$M3",
|
||||||
|
"M4": "$M4",
|
||||||
|
"M5": "$M5",
|
||||||
|
"M6": "$M6",
|
||||||
|
"M7": "$M7",
|
||||||
|
"M8": "$M8"
|
||||||
|
}"""
|
||||||
|
filepath.toFile().writeText(json)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
println("Error saving configuration: ${e.message}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
10
src/web/WsCommand.kt
Normal file
10
src/web/WsCommand.kt
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
package web
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonCreator
|
||||||
|
import com.fasterxml.jackson.annotation.JsonProperty
|
||||||
|
|
||||||
|
data class WsCommand @JsonCreator constructor(@JsonProperty("command")val command: String, @JsonProperty("data") val data: String?=null) {
|
||||||
|
override fun toString(): String {
|
||||||
|
return "WsCommand(command='$command', data='$data')"
|
||||||
|
}
|
||||||
|
}
|
||||||
11
src/web/WsReply.kt
Normal file
11
src/web/WsReply.kt
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
package web
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonCreator
|
||||||
|
import com.fasterxml.jackson.annotation.JsonProperty
|
||||||
|
|
||||||
|
data class WsReply @JsonCreator constructor(@JsonProperty("reply")val reply: String, @JsonProperty("data") val data: String?=null) {
|
||||||
|
|
||||||
|
override fun toString(): String {
|
||||||
|
return "WsReply(reply='$reply', data='$data')"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
package web;
|
package web;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import io.javalin.Javalin;
|
import io.javalin.Javalin;
|
||||||
import javafx.util.Pair;
|
import javafx.util.Pair;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
@@ -7,16 +8,19 @@ import org.slf4j.LoggerFactory;
|
|||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.function.BiFunction;
|
||||||
|
|
||||||
import static io.javalin.apibuilder.ApiBuilder.*;
|
import static io.javalin.apibuilder.ApiBuilder.*;
|
||||||
|
|
||||||
|
@SuppressWarnings("unused")
|
||||||
public class webApp {
|
public class webApp {
|
||||||
private final Javalin app;
|
private final Javalin app;
|
||||||
private final String listenAddress;
|
private final String listenAddress;
|
||||||
private final int listenPort;
|
private final int listenPort;
|
||||||
|
private final ObjectMapper objectMapper = new ObjectMapper();
|
||||||
private final Logger logger = LoggerFactory.getLogger(webApp.class);
|
private final Logger logger = LoggerFactory.getLogger(webApp.class);
|
||||||
private final Map<String, String> usermap = new HashMap<>();
|
private final Map<String, String> usermap = new HashMap<>();
|
||||||
public webApp(String listenAddress, int listenPort, Pair<String, String>... users) {
|
public webApp(String listenAddress, int listenPort, BiFunction<String,WsCommand, WsReply> callback, Pair<String, String>... users ) {
|
||||||
this.listenAddress = listenAddress;
|
this.listenAddress = listenAddress;
|
||||||
this.listenPort = listenPort;
|
this.listenPort = listenPort;
|
||||||
if (users != null){
|
if (users != null){
|
||||||
@@ -60,7 +64,14 @@ public class webApp {
|
|||||||
ws("/ws", wshandler -> wshandler.onMessage(wsMessageContext -> {
|
ws("/ws", wshandler -> wshandler.onMessage(wsMessageContext -> {
|
||||||
// Handle incoming WebSocket messages
|
// Handle incoming WebSocket messages
|
||||||
String message = wsMessageContext.message();
|
String message = wsMessageContext.message();
|
||||||
// Process the message as needed
|
try{
|
||||||
|
var command = objectMapper.readValue(message, WsCommand.class);
|
||||||
|
logger.info("Received command from pocreceiver.html/ws : {}", command);
|
||||||
|
var reply = callback.apply("pocreceiver", command);
|
||||||
|
wsMessageContext.send(reply);
|
||||||
|
} catch (Exception e){
|
||||||
|
logger.error("Error processing {} from pocreceiver.html/ws: {}",message, e.getMessage());
|
||||||
|
}
|
||||||
}));
|
}));
|
||||||
});
|
});
|
||||||
path("/prerecordedbroadcast.html", ()->{
|
path("/prerecordedbroadcast.html", ()->{
|
||||||
@@ -72,7 +83,14 @@ public class webApp {
|
|||||||
ws("/ws", wshandler -> wshandler.onMessage(wsMessageContext -> {
|
ws("/ws", wshandler -> wshandler.onMessage(wsMessageContext -> {
|
||||||
// Handle incoming WebSocket messages
|
// Handle incoming WebSocket messages
|
||||||
String message = wsMessageContext.message();
|
String message = wsMessageContext.message();
|
||||||
// Process the message as needed
|
try{
|
||||||
|
var command = objectMapper.readValue(message, WsCommand.class);
|
||||||
|
logger.info("Received command from prerecordedbroadcast.html/ws : {}", command);
|
||||||
|
var reply = callback.apply("prerecordedbroadcast", command);
|
||||||
|
wsMessageContext.send(reply);
|
||||||
|
} catch (Exception e){
|
||||||
|
logger.error("Error processing {} from prerecordedbroadcast.html/ws: {}",message, e.getMessage());
|
||||||
|
}
|
||||||
}));
|
}));
|
||||||
});
|
});
|
||||||
path("/setting.html", () ->{
|
path("/setting.html", () ->{
|
||||||
@@ -84,7 +102,17 @@ public class webApp {
|
|||||||
ws("/ws", wshandler -> wshandler.onMessage(wsMessageContext -> {
|
ws("/ws", wshandler -> wshandler.onMessage(wsMessageContext -> {
|
||||||
// Handle incoming WebSocket messages
|
// Handle incoming WebSocket messages
|
||||||
String message = wsMessageContext.message();
|
String message = wsMessageContext.message();
|
||||||
// Process the message as needed
|
try{
|
||||||
|
var command = objectMapper.readValue(message, WsCommand.class);
|
||||||
|
logger.info("Received command from setting.html/ws : {}", command);
|
||||||
|
var reply = callback.apply("setting", command);
|
||||||
|
logger.info("Replying to setting.html/ws : {}", reply);
|
||||||
|
wsMessageContext.send(reply);
|
||||||
|
} catch (Exception e){
|
||||||
|
logger.error("Error processing {} from setting.html/ws: {}", message, e.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}));
|
}));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user