Merge remote-tracking branch 'origin/master' into feature-webapp
This commit is contained in:
15
src/Main.kt
15
src/Main.kt
@@ -1,5 +1,6 @@
|
|||||||
import audio.AudioPlayer
|
import audio.AudioPlayer
|
||||||
import audio.ContentCache
|
import audio.ContentCache
|
||||||
|
import audio.TCPReceiver
|
||||||
import audio.UDPReceiver
|
import audio.UDPReceiver
|
||||||
import barix.BarixConnection
|
import barix.BarixConnection
|
||||||
import barix.TCP_Barix_Command_Server
|
import barix.TCP_Barix_Command_Server
|
||||||
@@ -27,6 +28,7 @@ lateinit var db: MariaDB
|
|||||||
lateinit var audioPlayer: AudioPlayer
|
lateinit var audioPlayer: AudioPlayer
|
||||||
val StreamerOutputs: MutableMap<String, BarixConnection> = HashMap()
|
val StreamerOutputs: MutableMap<String, BarixConnection> = HashMap()
|
||||||
lateinit var udpreceiver: UDPReceiver
|
lateinit var udpreceiver: UDPReceiver
|
||||||
|
lateinit var tcpreceiver: TCPReceiver
|
||||||
const val version = "0.0.2 (23/09/2025)"
|
const val version = "0.0.2 (23/09/2025)"
|
||||||
// AAS 64 channels
|
// AAS 64 channels
|
||||||
const val max_channel = 64
|
const val max_channel = 64
|
||||||
@@ -140,6 +142,15 @@ fun main() {
|
|||||||
Logger.error { "Failed to start UDP Receiver on port 5002" }
|
Logger.error { "Failed to start UDP Receiver on port 5002" }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tcpreceiver = TCPReceiver()
|
||||||
|
if (tcpreceiver.Start()) {
|
||||||
|
Logger.info { "TCP Receiver started on port 5002" }
|
||||||
|
} else {
|
||||||
|
Logger.error { "Failed to start TCP Receiver on port 5002" }
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
val androidserver = TCP_Android_Command_Server()
|
val androidserver = TCP_Android_Command_Server()
|
||||||
androidserver.StartTcpServer(5003){
|
androidserver.StartTcpServer(5003){
|
||||||
Logger.info { it }
|
Logger.info { it }
|
||||||
@@ -182,14 +193,18 @@ fun main() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
db.Add_Log("AAS"," Application started")
|
||||||
|
|
||||||
// shutdown hook
|
// shutdown hook
|
||||||
Runtime.getRuntime().addShutdownHook(Thread {
|
Runtime.getRuntime().addShutdownHook(Thread {
|
||||||
|
db.Add_Log("AAS"," Application stopping")
|
||||||
Logger.info { "Shutdown hook called, stopping services..." }
|
Logger.info { "Shutdown hook called, stopping services..." }
|
||||||
barixserver.StopTcpCommand()
|
barixserver.StopTcpCommand()
|
||||||
androidserver.StopTcpCommand()
|
androidserver.StopTcpCommand()
|
||||||
onlinechecker.cancel()
|
onlinechecker.cancel()
|
||||||
web.Stop()
|
web.Stop()
|
||||||
udpreceiver.Stop()
|
udpreceiver.Stop()
|
||||||
|
tcpreceiver.Stop()
|
||||||
audioPlayer.Close()
|
audioPlayer.Close()
|
||||||
db.close()
|
db.close()
|
||||||
Logger.info { "All services stopped, exiting application." }
|
Logger.info { "All services stopped, exiting application." }
|
||||||
|
|||||||
@@ -183,7 +183,9 @@ class MainExtension01 {
|
|||||||
*/
|
*/
|
||||||
fun Get_Soundbank_Data(value: String) : Map<String, String>? {
|
fun Get_Soundbank_Data(value: String) : Map<String, String>? {
|
||||||
if (ValidString(value)){
|
if (ValidString(value)){
|
||||||
|
//println("Parsing soundbank data from value: $value")
|
||||||
val values = value.split(" ").map { it.trim() }.filter { ValidString(it) }
|
val values = value.split(" ").map { it.trim() }.filter { ValidString(it) }
|
||||||
|
//println("Split into values: $values")
|
||||||
if (values.isNotEmpty()){
|
if (values.isNotEmpty()){
|
||||||
val result = mutableMapOf<String, String>()
|
val result = mutableMapOf<String, String>()
|
||||||
values.forEach {
|
values.forEach {
|
||||||
@@ -192,6 +194,7 @@ class MainExtension01 {
|
|||||||
// ada separator
|
// ada separator
|
||||||
val key = it.substring(0, separatorindex).trim().uppercase()
|
val key = it.substring(0, separatorindex).trim().uppercase()
|
||||||
val value = it.substring(separatorindex+1).trim().uppercase()
|
val value = it.substring(separatorindex+1).trim().uppercase()
|
||||||
|
//println("Got $key : $value")
|
||||||
if (ValidString(key) && ValidString(value)){
|
if (ValidString(key) && ValidString(value)){
|
||||||
if (SoundbankKeywords.contains(key)) result[key] = value
|
if (SoundbankKeywords.contains(key)) result[key] = value
|
||||||
}
|
}
|
||||||
@@ -338,11 +341,9 @@ class MainExtension01 {
|
|||||||
files.add(city.Path)
|
files.add(city.Path)
|
||||||
} else {
|
} else {
|
||||||
return Result_GetSoundbankFiles(false, "Invalid soundbank file ${city.Path} for tag=$_tag voicetype=${mb.Voice_Type} language=${mb.Language} ANN_ID=${mb.ANN_ID}")
|
return Result_GetSoundbankFiles(false, "Invalid soundbank file ${city.Path} for tag=$_tag voicetype=${mb.Voice_Type} language=${mb.Language} ANN_ID=${mb.ANN_ID}")
|
||||||
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return Result_GetSoundbankFiles(false, "No City found for tag=$_tag voicetype=${mb.Voice_Type} language=${mb.Language} ANN_ID=${mb.ANN_ID}")
|
return Result_GetSoundbankFiles(false, "No City found for tag=$_tag voicetype=${mb.Voice_Type} language=${mb.Language} ANN_ID=${mb.ANN_ID}")
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -537,7 +538,7 @@ class MainExtension01 {
|
|||||||
fun Read_Queue_Paging() : Boolean{
|
fun Read_Queue_Paging() : Boolean{
|
||||||
db.queuepagingDB.Get()
|
db.queuepagingDB.Get()
|
||||||
val list = db.queuepagingDB.List
|
val list = db.queuepagingDB.List
|
||||||
.filter { it.Source=="PAGING" }
|
.filter { it.Type=="PAGING" }
|
||||||
|
|
||||||
list.forEach { qp ->
|
list.forEach { qp ->
|
||||||
println("Processing $qp")
|
println("Processing $qp")
|
||||||
@@ -593,7 +594,7 @@ class MainExtension01 {
|
|||||||
fun Read_Queue_Shalat() : Boolean{
|
fun Read_Queue_Shalat() : Boolean{
|
||||||
db.queuepagingDB.Get()
|
db.queuepagingDB.Get()
|
||||||
val list = db.queuepagingDB.List
|
val list = db.queuepagingDB.List
|
||||||
.filter { it.Source=="SHALAT" }
|
.filter { it.Type=="SHALAT" }
|
||||||
list.forEach { qp ->
|
list.forEach { qp ->
|
||||||
println("Processing $qp")
|
println("Processing $qp")
|
||||||
if (qp.BroadcastZones.isNotBlank()){
|
if (qp.BroadcastZones.isNotBlank()){
|
||||||
@@ -852,13 +853,15 @@ class MainExtension01 {
|
|||||||
|
|
||||||
if (listafi.isNotEmpty()){
|
if (listafi.isNotEmpty()){
|
||||||
db.queuetableDB.DeleteByIndex(qa.index.toInt())
|
db.queuetableDB.DeleteByIndex(qa.index.toInt())
|
||||||
|
// bikin nama file ada postifx nya dari SB_TAGS, tapi spasi diganti underscore
|
||||||
val targetfile = SoundbankResult_directory.resolve(Make_WAV_FileName("Soundbank","")).toString()
|
// dan titik dua diganti dash
|
||||||
println("Writing to target WAV file: $targetfile")
|
val postfix = qa.SB_TAGS.replace(" ","_").replace(":","-")
|
||||||
|
val targetfile = SoundbankResult_directory.resolve(Make_WAV_FileName("${qa.Source}_${qa.Type}",postfix)).toString()
|
||||||
|
//println("Writing to target WAV file: $targetfile")
|
||||||
val result = audioPlayer.WavWriter(listafi, targetfile, true)
|
val result = audioPlayer.WavWriter(listafi, targetfile, true)
|
||||||
if (result.success){
|
if (result.success){
|
||||||
// file siap broadcast
|
// file siap broadcast
|
||||||
println("Successfully wrote WAV file: $targetfile")
|
//println("Successfully wrote WAV file: $targetfile")
|
||||||
val targetafi = audioPlayer.LoadAudioFile(targetfile)
|
val targetafi = audioPlayer.LoadAudioFile(targetfile)
|
||||||
if (targetafi.isValid()) {
|
if (targetafi.isValid()) {
|
||||||
ips.forEach { ip -> StreamerOutputs[ip]?.SendData(targetafi.bytes, { db.Add_Log("AAS", it) }, { db.Add_Log("AAS", it) }) }
|
ips.forEach { ip -> StreamerOutputs[ip]?.SendData(targetafi.bytes, { db.Add_Log("AAS", it) }, { db.Add_Log("AAS", it) }) }
|
||||||
|
|||||||
@@ -143,8 +143,7 @@ class AudioPlayer (var samplingrate: Int) {
|
|||||||
mem.write(0, data, 0, data.size)
|
mem.write(0, data, 0, data.size)
|
||||||
val pushresult = bass.BASS_StreamPutData(streamhandle, mem, data.size)
|
val pushresult = bass.BASS_StreamPutData(streamhandle, mem, data.size)
|
||||||
if (pushresult==-1){
|
if (pushresult==-1){
|
||||||
val errcode = bass.BASS_ErrorGetCode()
|
Logger.error { "BASS_StreamPutData failed: ${bass.BASS_ErrorGetCode()}" }
|
||||||
println("BASS_StreamPutData failed: $errcode")
|
|
||||||
}
|
}
|
||||||
return pushresult != -1
|
return pushresult != -1
|
||||||
}
|
}
|
||||||
@@ -154,32 +153,27 @@ class AudioPlayer (var samplingrate: Int) {
|
|||||||
if (withChime){
|
if (withChime){
|
||||||
val chup = contentCache.getAudioFile("chimeup")
|
val chup = contentCache.getAudioFile("chimeup")
|
||||||
if (chup!=null && chup.isValid()){
|
if (chup!=null && chup.isValid()){
|
||||||
if (pushData(chup.bytes)){
|
if (!pushData(chup.bytes)){
|
||||||
println("Chime up pushed")
|
|
||||||
} else {
|
|
||||||
all_success = false
|
all_success = false
|
||||||
println("Chime up failed")
|
Logger.error { "Failed to push Chime Up" }
|
||||||
}
|
}
|
||||||
} else println("Chime Up not valid")
|
} else Logger.error { "withChime=true, but Chime Up not available" }
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pushData(data)){
|
if (!pushData(data)){
|
||||||
println("Data pushed")
|
|
||||||
} else {
|
|
||||||
all_success = false
|
all_success = false
|
||||||
println("Data push failed")
|
Logger.error { "Failed to push Data ByteArray" }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (withChime){
|
if (withChime){
|
||||||
val chdn = contentCache.getAudioFile("chimedown")
|
val chdn = contentCache.getAudioFile("chimedown")
|
||||||
if (chdn!=null && chdn.isValid()){
|
if (chdn!=null && chdn.isValid()){
|
||||||
if (pushData(chdn.bytes)){
|
if (!pushData(chdn.bytes)){
|
||||||
println("Chime down pushed")
|
|
||||||
} else {
|
|
||||||
all_success = false
|
all_success = false
|
||||||
println("Chime down failed")
|
Logger.error { "Failed to push Chime Down" }
|
||||||
}
|
}
|
||||||
} else println("Chime Down not valid")
|
} else Logger.error { "withChime=true, but Chime Down not available" }
|
||||||
}
|
}
|
||||||
|
|
||||||
val readsize: Long = 1024 * 1024 // read 1 MB at a time
|
val readsize: Long = 1024 * 1024 // read 1 MB at a time
|
||||||
@@ -191,7 +185,6 @@ class AudioPlayer (var samplingrate: Int) {
|
|||||||
totalread += read
|
totalread += read
|
||||||
}
|
}
|
||||||
} while (read > 0)
|
} while (read > 0)
|
||||||
println("Finished reading stream data, total $totalread bytes read")
|
|
||||||
bassenc.BASS_Encode_Stop(encodehandle)
|
bassenc.BASS_Encode_Stop(encodehandle)
|
||||||
bass.BASS_StreamFree(streamhandle)
|
bass.BASS_StreamFree(streamhandle)
|
||||||
|
|
||||||
@@ -246,8 +239,7 @@ class AudioPlayer (var samplingrate: Int) {
|
|||||||
mem.write(0, data, 0, data.size)
|
mem.write(0, data, 0, data.size)
|
||||||
val pushresult = bass.BASS_StreamPutData(streamhandle, mem, data.size)
|
val pushresult = bass.BASS_StreamPutData(streamhandle, mem, data.size)
|
||||||
if (pushresult==-1){
|
if (pushresult==-1){
|
||||||
val errcode = bass.BASS_ErrorGetCode()
|
Logger.error { "BASS_StreamPutData failed: ${bass.BASS_ErrorGetCode()}" }
|
||||||
println("BASS_StreamPutData failed: $errcode")
|
|
||||||
}
|
}
|
||||||
return pushresult != -1
|
return pushresult != -1
|
||||||
}
|
}
|
||||||
@@ -258,39 +250,34 @@ class AudioPlayer (var samplingrate: Int) {
|
|||||||
if (withChime){
|
if (withChime){
|
||||||
val chup = contentCache.getAudioFile("chimeup")
|
val chup = contentCache.getAudioFile("chimeup")
|
||||||
if (chup!=null && chup.isValid()){
|
if (chup!=null && chup.isValid()){
|
||||||
if (pushData(chup.bytes)){
|
if (!pushData(chup.bytes)){
|
||||||
println("Chime up pushed")
|
|
||||||
} else {
|
|
||||||
allsuccess = false
|
allsuccess = false
|
||||||
println("Chime up failed")
|
Logger.error { "Failed to push Chime Up" }
|
||||||
}
|
}
|
||||||
} else println("Chime Up not valid")
|
} else Logger.error { "withChime=true, but Chime Up not available" }
|
||||||
}
|
}
|
||||||
sources.forEach { source ->
|
sources.forEach { source ->
|
||||||
if (source.isValid()) {
|
if (source.isValid()) {
|
||||||
// write the bytes to the stream
|
// write the bytes to the stream
|
||||||
if (pushData(source.bytes)){
|
if (!pushData(source.bytes)){
|
||||||
println("Source ${source.fileName} pushed")
|
|
||||||
} else {
|
|
||||||
allsuccess = false
|
allsuccess = false
|
||||||
println("Source ${source.fileName} push failed")
|
Logger.error { "Source ${source.fileName} push failed" }
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
allsuccess = false
|
allsuccess = false
|
||||||
println("Source ${source.fileName} is not valid")
|
Logger.error { "Not pushing Source=${source.fileName} because invalid" }
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
if (withChime){
|
if (withChime){
|
||||||
val chdn = contentCache.getAudioFile("chimedown")
|
val chdn = contentCache.getAudioFile("chimedown")
|
||||||
if (chdn!=null && chdn.isValid()){
|
if (chdn!=null && chdn.isValid()){
|
||||||
if (pushData(chdn.bytes)){
|
if (!pushData(chdn.bytes)){
|
||||||
println("Chime down pushed")
|
|
||||||
} else {
|
|
||||||
allsuccess = false
|
allsuccess = false
|
||||||
println("Chime down failed")
|
Logger.error { "Failed to push Chime Down" }
|
||||||
}
|
}
|
||||||
} else println("Chime Down not valid")
|
} else Logger.error { "withChime=true, but Chime Down not available"}
|
||||||
}
|
}
|
||||||
|
|
||||||
val readsize: Long = 1024 * 1024 // read 1 MB at a time
|
val readsize: Long = 1024 * 1024 // read 1 MB at a time
|
||||||
@@ -302,7 +289,6 @@ class AudioPlayer (var samplingrate: Int) {
|
|||||||
totalread += read
|
totalread += read
|
||||||
}
|
}
|
||||||
} while (read > 0)
|
} while (read > 0)
|
||||||
println("Finished reading stream data, total $totalread bytes read")
|
|
||||||
|
|
||||||
|
|
||||||
// close the encoding handle
|
// close the encoding handle
|
||||||
|
|||||||
104
src/audio/TCPReceiver.kt
Normal file
104
src/audio/TCPReceiver.kt
Normal file
@@ -0,0 +1,104 @@
|
|||||||
|
package audio
|
||||||
|
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import kotlinx.coroutines.runBlocking
|
||||||
|
import org.tinylog.Logger
|
||||||
|
import java.net.ServerSocket
|
||||||
|
import java.util.function.Consumer
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TCPReceiver is a class that listens for TCP connections on a specified port.
|
||||||
|
* for receiving PCMFILE from Android SAMI
|
||||||
|
*/
|
||||||
|
class TCPReceiver(val portnumber: Int = 5002){
|
||||||
|
private lateinit var server: ServerSocket
|
||||||
|
private var isRunning = false
|
||||||
|
private val dataCallback = mutableMapOf<String, Consumer<ByteArray>>()
|
||||||
|
private val isfinishd = mutableMapOf<String, Boolean>()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Start listening for TCP connections on the specified port.
|
||||||
|
* @return true if successful, false otherwise
|
||||||
|
*/
|
||||||
|
fun Start() : Boolean{
|
||||||
|
try{
|
||||||
|
server = ServerSocket(portnumber)
|
||||||
|
isRunning = true
|
||||||
|
Logger.info { "Server started at port $portnumber" }
|
||||||
|
CoroutineScope(Dispatchers.IO).launch {
|
||||||
|
while(isRunning){
|
||||||
|
try {
|
||||||
|
val client = server.accept()
|
||||||
|
val clientAddress = client.inetAddress.hostAddress
|
||||||
|
CoroutineScope(Dispatchers.IO).launch {
|
||||||
|
|
||||||
|
isfinishd[clientAddress] = false
|
||||||
|
var totalbytes = 0L
|
||||||
|
try{
|
||||||
|
val din = client.getInputStream()
|
||||||
|
Logger.info{ "Start receiving PCMFILE from Android with IP=${clientAddress}" }
|
||||||
|
|
||||||
|
do {
|
||||||
|
val buffer = ByteArray(16384)
|
||||||
|
val bytesRead = din.read(buffer)
|
||||||
|
if (bytesRead>0){
|
||||||
|
val data = ByteArray(bytesRead)
|
||||||
|
System.arraycopy(buffer, 0, data, 0, bytesRead)
|
||||||
|
//println("Received $bytesRead bytes from $clientAddress")
|
||||||
|
totalbytes+=bytesRead
|
||||||
|
dataCallback[clientAddress].let {
|
||||||
|
it?.accept(data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} while (bytesRead > 0)
|
||||||
|
} catch (e : Exception){
|
||||||
|
Logger.error { "Failed receiving data from $clientAddress, Message : ${e.message}" }
|
||||||
|
}
|
||||||
|
Logger.info { "Connection from $clientAddress ended, total bytesRead=$totalbytes" }
|
||||||
|
isfinishd[clientAddress] = true
|
||||||
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Logger.error { "Failed to accept socket, Message : ${e.message}" }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
} catch (e : Exception){
|
||||||
|
Logger.error { "Failed to Start Server at port $portnumber, Message : ${e.message}" }
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun RequestDataFrom(ipaddress: String, cb: Consumer<ByteArray>){
|
||||||
|
dataCallback[ipaddress] = cb
|
||||||
|
}
|
||||||
|
|
||||||
|
fun StopRequestDataFrom(ipaddress: String){
|
||||||
|
if (isfinishd[ipaddress] != null){
|
||||||
|
if (isfinishd[ipaddress]==false){
|
||||||
|
// belum selesai
|
||||||
|
//println("Waiting for receiving from $ipaddress to finish...")
|
||||||
|
runBlocking {
|
||||||
|
while (isfinishd[ipaddress] == false){
|
||||||
|
kotlinx.coroutines.delay(100)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//println("Removing callback for $ipaddress")
|
||||||
|
dataCallback.remove(ipaddress)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stop listening for TCP connections and close the server socket.
|
||||||
|
*/
|
||||||
|
fun Stop(){
|
||||||
|
if (isRunning){
|
||||||
|
isRunning = false
|
||||||
|
server.close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,7 +2,6 @@ package commandServer
|
|||||||
|
|
||||||
import codes.Somecodes.Companion.PagingResult_directory
|
import codes.Somecodes.Companion.PagingResult_directory
|
||||||
import codes.Somecodes.Companion.filenameformat
|
import codes.Somecodes.Companion.filenameformat
|
||||||
import org.tinylog.Logger
|
|
||||||
import java.io.ByteArrayOutputStream
|
import java.io.ByteArrayOutputStream
|
||||||
import java.nio.file.Path
|
import java.nio.file.Path
|
||||||
import java.time.LocalDateTime
|
import java.time.LocalDateTime
|
||||||
@@ -18,6 +17,11 @@ class PagingJob(val fromIP: String, val broadcastzones: String) {
|
|||||||
var totalBytesReceived = 0; private set
|
var totalBytesReceived = 0; private set
|
||||||
var isRunning = true; private set
|
var isRunning = true; private set
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Expected Size from PCMFILE android
|
||||||
|
*/
|
||||||
|
var expectedSize = 0
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds incoming audio data to the job.
|
* Adds incoming audio data to the job.
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package commandServer
|
|||||||
import audioPlayer
|
import audioPlayer
|
||||||
import codes.Somecodes.Companion.ValidString
|
import codes.Somecodes.Companion.ValidString
|
||||||
import codes.Somecodes.Companion.datetimeformat1
|
import codes.Somecodes.Companion.datetimeformat1
|
||||||
|
import content.Category
|
||||||
import content.Language
|
import content.Language
|
||||||
import database.Messagebank
|
import database.Messagebank
|
||||||
import database.QueuePaging
|
import database.QueuePaging
|
||||||
@@ -16,6 +17,7 @@ import kotlinx.coroutines.isActive
|
|||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.runBlocking
|
import kotlinx.coroutines.runBlocking
|
||||||
import org.tinylog.Logger
|
import org.tinylog.Logger
|
||||||
|
import tcpreceiver
|
||||||
import udpreceiver
|
import udpreceiver
|
||||||
import java.net.ServerSocket
|
import java.net.ServerSocket
|
||||||
import java.net.Socket
|
import java.net.Socket
|
||||||
@@ -167,102 +169,158 @@ class TCP_Android_Command_Server {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
"PCMFILE_START","STARTPAGINGAND" -> {
|
"PCMFILE_START" ->{
|
||||||
//TODO Paging IPM1 success, Paging IPMT gagal
|
// start sending PCM data from Android for paging
|
||||||
|
val size = parts.getOrElse(1) { "0" }.toInt()
|
||||||
|
val filename = parts.getOrElse(2) { "" }
|
||||||
|
val zones = parts.getOrElse(3) { "" }.replace(",",";")
|
||||||
|
if (size>0){
|
||||||
|
if (ValidString(filename)){
|
||||||
|
if (ValidString(zones)){
|
||||||
|
// create paging job
|
||||||
|
val pj = PagingJob(key, zones)
|
||||||
|
// ada expected size
|
||||||
|
pj.expectedSize = size
|
||||||
|
// masukin ke list
|
||||||
|
listOnGoingPaging[key] = pj
|
||||||
|
Logger.info{"PagingJob created for Android $key, zones: $zones, file: ${pj.filePath.absolutePathString()}"}
|
||||||
|
|
||||||
|
tcpreceiver.RequestDataFrom(key) {
|
||||||
|
// push data ke paging job
|
||||||
|
pj.addData(it, it.size)
|
||||||
|
}
|
||||||
|
cb.accept("PCMFILE_START;OK@")
|
||||||
|
Logger.info{"Android $key start sending PCM data, expecting $size bytes"}
|
||||||
|
return
|
||||||
|
|
||||||
|
} else logcb.accept("PCMFILE_START from Android $key failed, empty zones")
|
||||||
|
} else logcb.accept("PCMFILE_START from Android $key failed, empty filename")
|
||||||
|
} else logcb.accept("PCMFILE_START from Android $key failed, invalid size")
|
||||||
|
cb.accept("PCMFILE_START;NG@")
|
||||||
|
}
|
||||||
|
"PCMFILE_STOP" -> {
|
||||||
|
// stop sending PCM data from Android for paging
|
||||||
|
val pj = listOnGoingPaging[key]
|
||||||
|
if (pj!=null) {
|
||||||
|
listOnGoingPaging.remove(key)
|
||||||
|
tcpreceiver.StopRequestDataFrom(key)
|
||||||
|
// get remaining data
|
||||||
|
val data = pj.GetData()
|
||||||
|
pj.Close()
|
||||||
|
if (data.size==pj.expectedSize){
|
||||||
|
Logger.info { "Paging job closed from Android $key, total bytes received ${data.size}, writing to file ${pj.filePath.absolutePathString()}" }
|
||||||
|
val result = audioPlayer.WavWriter(data, pj.filePath.absolutePathString(), true)
|
||||||
|
if (result.success) {
|
||||||
|
val qp = QueuePaging(
|
||||||
|
0u,
|
||||||
|
LocalDateTime.now().format(datetimeformat1),
|
||||||
|
"ANDROID",
|
||||||
|
"PAGING",
|
||||||
|
pj.filePath.absolutePathString(),
|
||||||
|
pj.broadcastzones
|
||||||
|
)
|
||||||
|
if (db.queuepagingDB.Add(qp)) {
|
||||||
|
logcb.accept("Paging audio inserted to queue paging table from Android $key, file ${pj.filePath.absolutePathString()}")
|
||||||
|
cb.accept("PCMFILE_STOP;OK@")
|
||||||
|
return
|
||||||
|
} else logcb.accept("Failed to insert paging audio to queue paging table from Android $key, file ${pj.filePath.absolutePathString()}")
|
||||||
|
} else logcb.accept("Failed to write paging audio to file ${pj.filePath.absolutePathString()}, Message : ${result.message}")
|
||||||
|
} else logcb.accept("PCMFILE_STOP from Android $key received size ${data.size} does not match expected ${pj.expectedSize}")
|
||||||
|
} else logcb.accept("PCMFILE_STOP from Android $key failed, no ongoing PCM data receiving")
|
||||||
|
cb.accept("PCMFILE_STOP;NG@")
|
||||||
|
}
|
||||||
|
|
||||||
|
"STARTPAGINGAND" -> {
|
||||||
|
// Start Paging request from IPM
|
||||||
val zones = parts.getOrElse(1) { "" }.replace(",",";")
|
val zones = parts.getOrElse(1) { "" }.replace(",",";")
|
||||||
if (ValidString(zones)){
|
if (ValidString(zones)){
|
||||||
// create pagingjob
|
// create pagingjob
|
||||||
val pj = PagingJob(key, zones)
|
val pj = PagingJob(key, zones)
|
||||||
// masukin ke list
|
// masukin ke list
|
||||||
listOnGoingPaging[key] = pj
|
listOnGoingPaging[key] = pj
|
||||||
Logger.info{"PagingJob created for Android $key, zones: $zones, file: ${pj.filePath.absolutePathString()}"}
|
Logger.info{"PagingJob created for IPM $key, zones: $zones, file: ${pj.filePath.absolutePathString()}"}
|
||||||
|
|
||||||
// start minta data dari udpreceiver
|
// start minta data dari udpreceiver
|
||||||
udpreceiver.RequestDataFrom(key){
|
udpreceiver.RequestDataFrom(key){
|
||||||
// push data ke paging job
|
// push data ke paging job
|
||||||
pj.addData(it, it.size)
|
pj.addData(it, it.size)
|
||||||
}
|
}
|
||||||
logcb.accept("Paging started from Android $key")
|
logcb.accept("Paging started from IPM $key")
|
||||||
cb.accept(parts[0]+";OK@")
|
cb.accept("STARTPAGINGAND;OK@")
|
||||||
return
|
return
|
||||||
} else logcb.accept("Paging start from Android $key failed, empty zones")
|
} else logcb.accept("Paging start from IPM $key failed, empty zones")
|
||||||
cb.accept(parts[0]+";NG@")
|
cb.accept("STARTPAGINGAND;NG@")
|
||||||
}
|
}
|
||||||
|
|
||||||
"PCMFILE_STOP","STOPPAGINGAND" -> {
|
"STOPPAGINGAND" -> {
|
||||||
// TODO Paging IPM1 success, Paging IPMT gagal
|
// stop paging request from IPM
|
||||||
val pj = listOnGoingPaging[key]
|
val pj = listOnGoingPaging[key]
|
||||||
if (pj!=null){
|
if (pj!=null){
|
||||||
listOnGoingPaging.remove(key)
|
listOnGoingPaging.remove(key)
|
||||||
udpreceiver.StopRequestDataFrom(key)
|
udpreceiver.StopRequestDataFrom(key)
|
||||||
logcb.accept("Paging stopped from Android $key")
|
logcb.accept("Paging stopped from IPM $key")
|
||||||
cb.accept(parts[0]+";OK@")
|
|
||||||
// get remaining data
|
// get remaining data
|
||||||
val data = pj.GetData()
|
val data = pj.GetData()
|
||||||
pj.Close()
|
pj.Close()
|
||||||
Logger.info{"Paging job closed from Android $key, total bytes received ${data.size}, writing to file ${pj.filePath.absolutePathString()}"}
|
Logger.info{"Paging job closed from IPM $key, total bytes received ${data.size}, writing to file ${pj.filePath.absolutePathString()}"}
|
||||||
val result = audioPlayer.WavWriter(data, pj.filePath.absolutePathString(), true)
|
val result = audioPlayer.WavWriter(data, pj.filePath.absolutePathString(), true)
|
||||||
if (result.success){
|
if (result.success){
|
||||||
val qp = QueuePaging(
|
val qp = QueuePaging(
|
||||||
0u,
|
0u,
|
||||||
LocalDateTime.now().format(datetimeformat1),
|
LocalDateTime.now().format(datetimeformat1),
|
||||||
|
"IPM",
|
||||||
"PAGING",
|
"PAGING",
|
||||||
"NORMAL",
|
|
||||||
pj.filePath.absolutePathString(),
|
pj.filePath.absolutePathString(),
|
||||||
pj.broadcastzones
|
pj.broadcastzones
|
||||||
)
|
)
|
||||||
if (db.queuepagingDB.Add(qp)){
|
if (db.queuepagingDB.Add(qp)){
|
||||||
logcb.accept("Paging audio inserted to queue paging table from Android $key, file ${pj.filePath.absolutePathString()}")
|
logcb.accept("Paging audio inserted to queue paging table from IPM $key, file ${pj.filePath.absolutePathString()}")
|
||||||
cb.accept(parts[0]+";OK@")
|
cb.accept("STOPPAGINGAND;OK@")
|
||||||
} else {
|
return
|
||||||
logcb.accept("Failed to insert paging audio to queue paging table from Android $key, file ${pj.filePath.absolutePathString()}")
|
} else logcb.accept("Failed to insert paging audio to queue paging table from IPM $key, file ${pj.filePath.absolutePathString()}")
|
||||||
cb.accept(parts[0]+";NG@")
|
} else logcb.accept("Failed to write paging audio to file ${pj.filePath.absolutePathString()}, Message : ${result.message}")
|
||||||
}
|
} else logcb.accept("Paging stop from IPM $key failed, no ongoing paging")
|
||||||
} else {
|
cb.accept("STOPPAGINGAND;NG@")
|
||||||
logcb.accept("Failed to write paging audio to file ${pj.filePath.absolutePathString()}, Message : ${result.message}")
|
|
||||||
cb.accept(parts[0]+";NG@")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
} else {
|
|
||||||
logcb.accept("Paging stop from Android $key failed, no ongoing paging")
|
|
||||||
cb.accept(parts[0]+";NG@")
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
"CANCELPAGINGAND" -> {
|
"CANCELPAGINGAND" -> {
|
||||||
// TODO Cancel Paging IPM1 success, IPMT gagal
|
// cancel paging request from IPM
|
||||||
val pj = listOnGoingPaging[key]
|
val pj = listOnGoingPaging[key]
|
||||||
if (pj!=null){
|
if (pj!=null){
|
||||||
pj.Close()
|
pj.Close()
|
||||||
listOnGoingPaging.remove(key)
|
listOnGoingPaging.remove(key)
|
||||||
udpreceiver.StopRequestDataFrom(key)
|
udpreceiver.StopRequestDataFrom(key)
|
||||||
logcb.accept("Paging from Android $key cancelled")
|
logcb.accept("Paging from IPM $key cancelled")
|
||||||
cb.accept("CANCELPAGINGAND;OK@")
|
cb.accept("CANCELPAGINGAND;OK@")
|
||||||
return
|
return
|
||||||
} else logcb.accept("Paging cancel from Android $key failed, no ongoing paging")
|
} else logcb.accept("Paging cancel from IPM $key failed, no ongoing paging")
|
||||||
cb.accept("CANCELPAGINGAND;NG@")
|
cb.accept("CANCELPAGINGAND;NG@")
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
"STARTINITIALIZE" -> {
|
"STARTINITIALIZE" -> {
|
||||||
// TODO STARTINITIALIZE IPM1 success, IPMT gagal
|
|
||||||
val username = parts.getOrElse(1) { "" }
|
val username = parts.getOrElse(1) { "" }
|
||||||
if (ValidString(username)){
|
if (ValidString(username)){
|
||||||
val userlogin = listUserLogin.find { it.username == username }
|
val userlogin = listUserLogin.find { it.username == username }
|
||||||
if (userlogin != null){
|
if (userlogin != null){
|
||||||
val userdb = db.userDB.List.find { it.username == username }
|
val userdb = db.userDB.List.find { it.username == username }
|
||||||
if (userdb != null){
|
if (userdb != null){
|
||||||
|
println("Sending initialization data to $key with username $username")
|
||||||
val result = StringBuilder()
|
val result = StringBuilder()
|
||||||
|
// kirim Zone
|
||||||
result.append("ZONE")
|
result.append("ZONE")
|
||||||
userdb.broadcastzones.split(";").map { it.trim() }.filter { it.isNotBlank() }.forEach {
|
userdb.broadcastzones.split(";").map { it.trim() }.filter { it.isNotBlank() }.forEach {
|
||||||
result.append(";")
|
result.append(";")
|
||||||
result.append(it)
|
result.append(it)
|
||||||
}
|
}
|
||||||
result.append("@")
|
result.append("@")
|
||||||
|
cb.accept(result.toString())
|
||||||
|
|
||||||
|
// kirim MSGTOTAL
|
||||||
|
result.clear()
|
||||||
val VARMESSAGES = mutableListOf<Messagebank>()
|
val VARMESSAGES = mutableListOf<Messagebank>()
|
||||||
|
result.append("MSGTOTAL;")
|
||||||
userdb.messagebank_ann_id
|
userdb.messagebank_ann_id
|
||||||
// messagebank_ann_id adalah rentengan ANN_ID (digit) yang dipisah dengan ;
|
// messagebank_ann_id adalah rentengan ANN_ID (digit) yang dipisah dengan ;
|
||||||
.split(";")
|
.split(";")
|
||||||
@@ -270,112 +328,272 @@ class TCP_Android_Command_Server {
|
|||||||
.map { it.trim() }
|
.map { it.trim() }
|
||||||
// bukan string kosong antar dua tanda ;
|
// bukan string kosong antar dua tanda ;
|
||||||
.filter { it.isNotBlank() }
|
.filter { it.isNotBlank() }
|
||||||
// beneran digit semua
|
|
||||||
.filter { xx -> xx.all{it.isDigit()} }
|
|
||||||
// iterasi setiap ANN_ID
|
// iterasi setiap ANN_ID
|
||||||
.forEach { annid ->
|
.forEach { annid ->
|
||||||
// masukin ke VARMESSAGES yang unik secara ANN_ID dan Language
|
// masukin ke VARMESSAGES yang unik secara ANN_ID dan Language
|
||||||
val xx = db.messageDB.List
|
val xx = db.messageDB.List
|
||||||
.filter{ it.ANN_ID == annid.toUInt() }
|
.filter{ it.ANN_ID == annid.toUInt() }
|
||||||
.distinctBy { it.Language }
|
.distinctBy { it.ANN_ID }
|
||||||
VARMESSAGES.addAll(xx)
|
VARMESSAGES.addAll(xx)
|
||||||
}
|
}
|
||||||
result.append("MSGTOTAL;").append(VARMESSAGES.size).append("@")
|
result.append(VARMESSAGES.size).append("@")
|
||||||
// VAR AP TOTAL
|
|
||||||
val VARAPTOTAL = mutableListOf<Soundbank>()
|
|
||||||
val al_split = userdb.airline_tags.split(";").map { it.trim() }.filter { it.isNotBlank() }
|
|
||||||
al_split.forEach {
|
|
||||||
val sb = db.Find_Soundbank_AirplaneName(it).firstOrNull()
|
|
||||||
if (sb != null) VARAPTOTAL.add(sb)
|
|
||||||
}
|
|
||||||
result.append("VARAPTOTAL;").append(VARAPTOTAL.size).append("@")
|
|
||||||
// VAR CITY TOTAL
|
|
||||||
val VARCITYTOTAL = mutableListOf<Soundbank>()
|
|
||||||
val ct_split = userdb.city_tags.split(";").map { it.trim() }.filter { it.isNotBlank() }
|
|
||||||
ct_split.forEach {
|
|
||||||
val sb = db.Find_Soundbank_City(it).firstOrNull()
|
|
||||||
if (sb != null) VARCITYTOTAL.add(sb)
|
|
||||||
}
|
|
||||||
result.append("VARCITYTOTAL;").append(VARCITYTOTAL.size).append("@")
|
|
||||||
// VAR PLACES TOTAL
|
|
||||||
val VARPLACESTOTAL = mutableListOf<Soundbank>()
|
|
||||||
// sb_split.forEach {
|
|
||||||
// val sb = db.Find_Soundbank_Places(it).firstOrNull()
|
|
||||||
// if (sb != null) VARPLACESTOTAL.add(sb)
|
|
||||||
// }
|
|
||||||
result.append("VARPLACESTOTAL;").append(VARPLACESTOTAL.size).append("@")
|
|
||||||
// VAR SHALAT TOTAL
|
|
||||||
val VARSHALATTOTAL = mutableListOf<Soundbank>()
|
|
||||||
// sb_split.forEach {
|
|
||||||
// val sb = db.Find_Soundbank_Shalat(it).firstOrNull()
|
|
||||||
// if (sb != null) VARSHALATTOTAL.add(sb)
|
|
||||||
// }
|
|
||||||
result.append("VARSHALATTOTAL;").append(VARSHALATTOTAL.size).append("@")
|
|
||||||
// VAR SEQUENCE TOTAL
|
|
||||||
val VARSEQUENCETOTAL = mutableListOf<Soundbank>()
|
|
||||||
// sb_split.forEach {
|
|
||||||
// val sb = db.Find_Soundbank_Sequence(it).firstOrNull()
|
|
||||||
// if (sb != null) VARSEQUENCETOTAL.add(sb)
|
|
||||||
// }
|
|
||||||
// VAR REASON TOTAL
|
|
||||||
val VARREASONTOTAL = mutableListOf<Soundbank>()
|
|
||||||
// sb_split.forEach {
|
|
||||||
// val sb = db.Find_Soundbank_Reason(it).firstOrNull()
|
|
||||||
// if (sb != null) VARREASONTOTAL.add(sb)
|
|
||||||
// }
|
|
||||||
result.append("VARREASONTOTAL;").append(VARREASONTOTAL.size).append("@")
|
|
||||||
// VAR PROCEDURE TOTAL
|
|
||||||
val VARPROCEDURETOTAL = mutableListOf<Soundbank>()
|
|
||||||
// sb_split.forEach {
|
|
||||||
// val sb = db.Find_Soundbank_Procedure(it).firstOrNull()
|
|
||||||
// if (sb != null) VARPROCEDURETOTAL.add(sb)
|
|
||||||
// }
|
|
||||||
result.append("VARPROCEDURETOTAL;").append(VARPROCEDURETOTAL.size).append("@")
|
|
||||||
// send to sender
|
|
||||||
cb.accept(result.toString())
|
cb.accept(result.toString())
|
||||||
|
|
||||||
|
// kirim VARAPTOTAL
|
||||||
result.clear()
|
result.clear()
|
||||||
|
result.append("VARAPTOTAL;")
|
||||||
|
val VARAPTOTAL = mutableListOf<Soundbank>()
|
||||||
|
userdb.airline_tags
|
||||||
|
.split(";")
|
||||||
|
.map { it.trim() }
|
||||||
|
.filter { it.isNotBlank() }
|
||||||
|
.forEach { al ->
|
||||||
|
val sb = db.soundDB.List
|
||||||
|
.filter { it.Category.equals(Category.Airplane_Name.name, true) }
|
||||||
|
.filter { it.TAG.equals(al, true)}
|
||||||
|
.distinctBy { it.TAG }
|
||||||
|
VARAPTOTAL.addAll(sb)
|
||||||
|
}
|
||||||
|
result.append(VARAPTOTAL.size).append("@")
|
||||||
|
cb.accept(result.toString())
|
||||||
|
|
||||||
|
// kirim VARCITYTOTAL
|
||||||
|
result.clear()
|
||||||
|
result.append("VARCITYTOTAL;")
|
||||||
|
val VARCITYTOTAL = mutableListOf<Soundbank>()
|
||||||
|
userdb.city_tags
|
||||||
|
.split(";")
|
||||||
|
.map { it.trim() }
|
||||||
|
.filter { it.isNotBlank() }
|
||||||
|
.forEach { ct ->
|
||||||
|
val sb = db.soundDB.List
|
||||||
|
.filter { it.Category.equals(Category.City.name, true) }
|
||||||
|
.filter { it.TAG.equals(ct, true)}
|
||||||
|
.distinctBy { it.TAG }
|
||||||
|
VARCITYTOTAL.addAll(sb)
|
||||||
|
}
|
||||||
|
result.append(VARCITYTOTAL.size).append("@")
|
||||||
|
cb.accept(result.toString())
|
||||||
|
|
||||||
|
// kirim VARPLACESTOTAL
|
||||||
|
result.clear()
|
||||||
|
result.append("VARPLACESTOTAL;")
|
||||||
|
val VARPLACESTOTAL = mutableListOf<Soundbank>()
|
||||||
|
db.soundDB.List
|
||||||
|
.filter { it.Category.equals(Category.Places.name, true) }
|
||||||
|
.distinctBy { it.TAG }
|
||||||
|
.forEach {
|
||||||
|
VARPLACESTOTAL.add(it)
|
||||||
|
}
|
||||||
|
result.append(VARPLACESTOTAL.size).append("@")
|
||||||
|
cb.accept(result.toString())
|
||||||
|
|
||||||
|
// kirim VARSHALATTOTAL
|
||||||
|
result.clear()
|
||||||
|
result.append("VARSHALATTOTAL;")
|
||||||
|
val VARSHALATTOTAL = mutableListOf<Soundbank>()
|
||||||
|
db.soundDB.List
|
||||||
|
.filter { it.Category.equals(Category.Shalat.name, true) }
|
||||||
|
.distinctBy { it.TAG }
|
||||||
|
.forEach {
|
||||||
|
VARSHALATTOTAL.add(it)
|
||||||
|
}
|
||||||
|
result.append(VARSHALATTOTAL.size).append("@")
|
||||||
|
cb.accept(result.toString())
|
||||||
|
|
||||||
|
// kirim VARSEQUENCETOTAL
|
||||||
|
result.clear()
|
||||||
|
result.append("VARSEQUENCETOTAL;")
|
||||||
|
val VARSEQUENCETOTAL = mutableListOf<Soundbank>()
|
||||||
|
db.soundDB.List
|
||||||
|
.filter { it.Category.equals(Category.Sequence.name, true) }
|
||||||
|
.distinctBy { it.TAG }
|
||||||
|
.forEach {
|
||||||
|
VARSEQUENCETOTAL.add(it)
|
||||||
|
}
|
||||||
|
result.append(VARSEQUENCETOTAL.size).append("@")
|
||||||
|
cb.accept(result.toString())
|
||||||
|
|
||||||
|
// kirim VARREASONTOTAL
|
||||||
|
result.clear()
|
||||||
|
result.append("VARREASONTOTAL;")
|
||||||
|
val VARREASONTOTAL = mutableListOf<Soundbank>()
|
||||||
|
db.soundDB.List
|
||||||
|
.filter { it.Category.equals(Category.Reason.name, true) }
|
||||||
|
.distinctBy { it.TAG }
|
||||||
|
.forEach {
|
||||||
|
VARREASONTOTAL.add(it)
|
||||||
|
}
|
||||||
|
result.append(VARREASONTOTAL.size).append("@")
|
||||||
|
cb.accept(result.toString())
|
||||||
|
|
||||||
|
// kirim VARPROCEDURETOTAL
|
||||||
|
val VARPROCEDURETOTAL = mutableListOf<Soundbank>()
|
||||||
|
result.clear()
|
||||||
|
result.append("VARPROCEDURETOTAL;")
|
||||||
|
db.soundDB.List
|
||||||
|
.filter { it.Category.equals(Category.Procedure.name, true) }
|
||||||
|
.distinctBy { it.TAG }
|
||||||
|
.forEach {
|
||||||
|
VARPROCEDURETOTAL.add(it)
|
||||||
|
}
|
||||||
|
result.append(VARPROCEDURETOTAL.size).append("@")
|
||||||
|
cb.accept(result.toString())
|
||||||
|
|
||||||
|
// kirim VARGATETOTAL
|
||||||
|
val VARGATETOTAL = mutableListOf<Soundbank>()
|
||||||
|
result.clear()
|
||||||
|
result.append("VARGATETOTAL;")
|
||||||
|
db.soundDB.List
|
||||||
|
.filter { it.Category.equals(Category.Gate.name, true) }
|
||||||
|
.distinctBy { it.TAG }
|
||||||
|
.forEach {
|
||||||
|
VARGATETOTAL.add(it)
|
||||||
|
}
|
||||||
|
result.append(VARGATETOTAL.size).append("@")
|
||||||
|
cb.accept(result.toString())
|
||||||
|
|
||||||
|
// kirim VARCOMPENSATIONTOTAL
|
||||||
|
result.clear()
|
||||||
|
result.append("VARCOMPENSATIONTOTAL;")
|
||||||
|
val VARCOMPENSATIONTOTAL = mutableListOf<Soundbank>()
|
||||||
|
db.soundDB.List
|
||||||
|
.filter { it.Category.equals(Category.Compensation.name, true) }
|
||||||
|
.distinctBy { it.TAG }
|
||||||
|
.forEach {
|
||||||
|
VARCOMPENSATIONTOTAL.add(it)
|
||||||
|
}
|
||||||
|
result.append(VARCOMPENSATIONTOTAL.size).append("@")
|
||||||
|
cb.accept(result.toString())
|
||||||
|
|
||||||
|
// kirim VARGREETINGTOTAL
|
||||||
|
result.clear()
|
||||||
|
result.append("VARGREETINGTOTAL;")
|
||||||
|
val VARGREETINGTOTAL = mutableListOf<Soundbank>()
|
||||||
|
db.soundDB.List
|
||||||
|
.filter { it.Category.equals(Category.Greeting.name, true) }
|
||||||
|
.distinctBy { it.TAG }
|
||||||
|
.forEach {
|
||||||
|
VARGREETINGTOTAL.add(it)
|
||||||
|
}
|
||||||
|
result.append(VARGREETINGTOTAL.size).append("@")
|
||||||
|
cb.accept(result.toString())
|
||||||
|
|
||||||
//Append MSG, for Android only Indonesia and English
|
//Append MSG, for Android only Indonesia and English
|
||||||
VARMESSAGES.groupBy { it.ANN_ID }.forEach { (ann_id, value) ->
|
if (VARMESSAGES.isNotEmpty()) {
|
||||||
result.append("MSG;").append(ann_id)
|
result.clear()
|
||||||
result.append(";")
|
VARMESSAGES.forEachIndexed { index, msg ->
|
||||||
value.find { it.Language.equals(Language.INDONESIA.name, true) }?.let {result.append(it.Message_Detail)} ?: result.append("NA")
|
|
||||||
result.append(";")
|
val ann_id = msg.ANN_ID
|
||||||
value.find {it.Language.equals(Language.ENGLISH.name, true) }?.let {result.append(it.Message_Detail)} ?: result.append("NA")
|
val msg_indo = db.messageDB.List.find {
|
||||||
result.append("@")
|
it.ANN_ID == ann_id && it.Language.equals(
|
||||||
|
Language.INDONESIA.name,
|
||||||
|
true
|
||||||
|
)
|
||||||
|
}
|
||||||
|
val msg_eng = db.messageDB.List.find {
|
||||||
|
it.ANN_ID == ann_id && it.Language.equals(
|
||||||
|
Language.ENGLISH.name,
|
||||||
|
true
|
||||||
|
)
|
||||||
|
}
|
||||||
|
val description = msg_indo?.Description ?: msg_eng?.Description ?: "UNKNOWN"
|
||||||
|
result.append("MSG;$index;$ann_id;$description;")
|
||||||
|
result.append(msg_indo?.Message_Detail ?:"").append(";")
|
||||||
|
result.append(msg_eng?.Message_Detail ?:"").append("@")
|
||||||
|
}
|
||||||
|
cb.accept(result.toString())
|
||||||
}
|
}
|
||||||
|
|
||||||
// append VARAP
|
// append VARAP
|
||||||
VARAPTOTAL.distinctBy { it.Description }.forEachIndexed { index, soundbank ->
|
if (VARAPTOTAL.isNotEmpty()) {
|
||||||
result.append("VARAP;").append(index).append(";").append(soundbank.TAG).append(";").append(soundbank.Description).append("@")
|
result.clear()
|
||||||
|
VARAPTOTAL.forEachIndexed { index, sb ->
|
||||||
|
result.append("VARAP;$index;${sb.TAG};${sb.Description}@")
|
||||||
|
}
|
||||||
|
cb.accept(result.toString())
|
||||||
}
|
}
|
||||||
|
|
||||||
// append VARCITY
|
// append VARCITY
|
||||||
VARCITYTOTAL.distinctBy { it.Description }.forEachIndexed { index, soundbank ->
|
if (VARCITYTOTAL.isNotEmpty()) {
|
||||||
result.append("VARCITY;").append(index).append(";").append(soundbank.TAG).append(";").append(soundbank.Description).append("@")
|
result.clear()
|
||||||
|
VARCITYTOTAL.forEachIndexed { index, sb ->
|
||||||
|
result.append("VARCITY;$index;${sb.TAG};${sb.Description}@")
|
||||||
|
}
|
||||||
|
cb.accept(result.toString())
|
||||||
}
|
}
|
||||||
|
|
||||||
// append VARPLACES
|
// append VARPLACES
|
||||||
VARPLACESTOTAL.distinctBy { it.Description }.forEachIndexed { index, soundbank ->
|
if (VARPLACESTOTAL.isNotEmpty()) {
|
||||||
result.append("VARPLACES;").append(index).append(";").append(soundbank.TAG).append(";").append(soundbank.Description).append("@")
|
result.clear()
|
||||||
|
VARPLACESTOTAL.forEachIndexed { index, sb ->
|
||||||
|
result.append("VARPLACES;$index;${sb.TAG};${sb.Description}@")
|
||||||
|
}
|
||||||
|
cb.accept(result.toString())
|
||||||
}
|
}
|
||||||
// append VARSHALAT
|
// append VARSHALAT
|
||||||
VARSHALATTOTAL.distinctBy { it.Description }.forEachIndexed { index, soundbank ->
|
if (VARSHALATTOTAL.isNotEmpty()) {
|
||||||
result.append("VARSHALAT;").append(index).append(";").append(soundbank.TAG).append(";").append(soundbank.Description).append("@")
|
result.clear()
|
||||||
|
VARSHALATTOTAL.forEachIndexed { index, sb ->
|
||||||
|
result.append("VARSHALAT;$index;${sb.TAG};${sb.Description}@")
|
||||||
|
}
|
||||||
|
cb.accept(result.toString())
|
||||||
}
|
}
|
||||||
|
|
||||||
// append VARSEQUENCE
|
// append VARSEQUENCE
|
||||||
VARSEQUENCETOTAL.distinctBy { it.Description }.forEachIndexed { index, soundbank ->
|
if (VARSEQUENCETOTAL.isNotEmpty()) {
|
||||||
result.append("VARSEQUENCE;").append(index).append(";").append(soundbank.TAG).append(";").append(soundbank.Description).append("@")
|
result.clear()
|
||||||
|
VARSEQUENCETOTAL.forEachIndexed { index, sb ->
|
||||||
|
result.append("VARSEQUENCE;$index;${sb.TAG};${sb.Description}@")
|
||||||
|
}
|
||||||
|
cb.accept(result.toString())
|
||||||
}
|
}
|
||||||
|
|
||||||
// append VARREASON
|
// append VARREASON
|
||||||
VARREASONTOTAL.distinctBy { it.Description }.forEachIndexed { index, soundbank ->
|
if (VARREASONTOTAL.isNotEmpty()) {
|
||||||
result.append("VARREASON;").append(index).append(";").append(soundbank.TAG).append(";").append(soundbank.Description).append("@")
|
result.clear()
|
||||||
|
VARREASONTOTAL.forEachIndexed { index, sb ->
|
||||||
|
result.append("VARREASON;$index;${sb.TAG};${sb.Description}@")
|
||||||
|
}
|
||||||
|
cb.accept(result.toString())
|
||||||
}
|
}
|
||||||
|
|
||||||
// append VARPROCEDURE
|
// append VARPROCEDURE
|
||||||
VARPROCEDURETOTAL.distinctBy { it.Description }.forEachIndexed { index, soundbank ->
|
if (VARPROCEDURETOTAL.isNotEmpty()) {
|
||||||
result.append("VARPROCEDURE;").append(index).append(";").append(soundbank.TAG).append(";").append(soundbank.Description).append("@")
|
result.clear()
|
||||||
|
VARPROCEDURETOTAL.forEachIndexed { index, sb ->
|
||||||
|
result.append("VARPROCEDURE;$index;${sb.TAG};${sb.Description}@")
|
||||||
|
}
|
||||||
|
cb.accept(result.toString())
|
||||||
}
|
}
|
||||||
// send to sender
|
|
||||||
cb.accept(result.toString())
|
// append VARGATE
|
||||||
|
if (VARGATETOTAL.isNotEmpty()) {
|
||||||
|
result.clear()
|
||||||
|
VARGATETOTAL.forEachIndexed { index, sb ->
|
||||||
|
result.append("VARGATE;$index;${sb.TAG};${sb.Description}@")
|
||||||
|
}
|
||||||
|
cb.accept(result.toString())
|
||||||
|
}
|
||||||
|
|
||||||
|
// append VARCOMPENSATION
|
||||||
|
if (VARCOMPENSATIONTOTAL.isNotEmpty()) {
|
||||||
|
result.clear()
|
||||||
|
VARCOMPENSATIONTOTAL.forEachIndexed { index, sb ->
|
||||||
|
result.append("VARCOMPENSATION;$index;${sb.TAG};${sb.Description}@")
|
||||||
|
}
|
||||||
|
cb.accept(result.toString())
|
||||||
|
}
|
||||||
|
|
||||||
|
// append VARGREETING
|
||||||
|
if (VARGREETINGTOTAL.isNotEmpty()) {
|
||||||
|
result.clear()
|
||||||
|
VARGREETINGTOTAL.forEachIndexed { index, sb ->
|
||||||
|
result.append("VARGREETING;$index;${sb.TAG};${sb.Description}@")
|
||||||
|
}
|
||||||
|
cb.accept(result.toString())
|
||||||
|
}
|
||||||
|
|
||||||
logcb.accept("All variables sent to $key with username $username")
|
logcb.accept("All variables sent to $key with username $username")
|
||||||
return
|
return
|
||||||
} else logcb.accept("STARTINITIALIZE failed from $key with username $username not found in userDB")
|
} else logcb.accept("STARTINITIALIZE failed from $key with username $username not found in userDB")
|
||||||
@@ -387,8 +605,11 @@ class TCP_Android_Command_Server {
|
|||||||
"BROADCASTAND" -> {
|
"BROADCASTAND" -> {
|
||||||
// semi auto dari android, masukin ke queue table
|
// semi auto dari android, masukin ke queue table
|
||||||
val desc = parts.getOrElse(1) { "" }
|
val desc = parts.getOrElse(1) { "" }
|
||||||
|
// language bisa lebih dari satu, dipisah dengan koma
|
||||||
val lang = parts.getOrElse(2) { "" }.replace(",",";")
|
val lang = parts.getOrElse(2) { "" }.replace(",",";")
|
||||||
|
// tags bisa lebih dari satu, dipisah dengan spasi
|
||||||
val tags = parts.getOrElse(3) { "" }.replace(",",";")
|
val tags = parts.getOrElse(3) { "" }.replace(",",";")
|
||||||
|
// zone bisa lebih dari satu, dipisah dengan koma
|
||||||
val zone = parts.getOrElse(4) { "" }.replace(",",";")
|
val zone = parts.getOrElse(4) { "" }.replace(",",";")
|
||||||
if (ValidString(desc)){
|
if (ValidString(desc)){
|
||||||
if (ValidString(lang)){
|
if (ValidString(lang)){
|
||||||
@@ -414,7 +635,7 @@ class TCP_Android_Command_Server {
|
|||||||
} else logcb.accept("Broadcsast request from Android $key username=${listUserLogin.find { it.ip==key }?.username ?: "UNKNOWN"} failed, empty tags")
|
} else logcb.accept("Broadcsast request from Android $key username=${listUserLogin.find { it.ip==key }?.username ?: "UNKNOWN"} failed, empty tags")
|
||||||
} else logcb.accept("Broadcast request from Android $key username=${listUserLogin.find { it.ip==key }?.username ?: "UNKNOWN"} failed, empty language")
|
} else logcb.accept("Broadcast request from Android $key username=${listUserLogin.find { it.ip==key }?.username ?: "UNKNOWN"} failed, empty language")
|
||||||
} else logcb.accept("Broadcast request from Android $key username=${listUserLogin.find { it.ip==key }?.username ?: "UNKNOWN"} failed, empty description")
|
} else logcb.accept("Broadcast request from Android $key username=${listUserLogin.find { it.ip==key }?.username ?: "UNKNOWN"} failed, empty description")
|
||||||
cb.accept("NG@")
|
cb.accept("BROADCASTAND;NG@")
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -14,5 +14,8 @@ enum class Category(name: String) {
|
|||||||
Birthday("Birthday"),
|
Birthday("Birthday"),
|
||||||
Reason("Reason"),
|
Reason("Reason"),
|
||||||
Sequence("Sequence"),
|
Sequence("Sequence"),
|
||||||
Procedure("Procedure");
|
Procedure("Procedure"),
|
||||||
|
Gate("Gate"),
|
||||||
|
Greeting("Greeting"),
|
||||||
|
Compensation("Compensation");
|
||||||
}
|
}
|
||||||
@@ -1179,7 +1179,7 @@ class MariaDB(
|
|||||||
override fun Add(data: QueueTable): Boolean {
|
override fun Add(data: QueueTable): Boolean {
|
||||||
try {
|
try {
|
||||||
val statement = connection.prepareStatement(
|
val statement = connection.prepareStatement(
|
||||||
"INSERT INTO ${super.dbName} (Date_Time, Source, Type, Message, SB_TAGS, BroadcastZones, Repeat, Language) VALUES (?, ?, ?, ?, ?, ?, ?, ?)"
|
"INSERT INTO ${super.dbName} (`Date_Time`, `Source`, `Type`, `Message`, `SB_TAGS`, `BroadcastZones`, `Repeat`, `Language`) VALUES (?, ?, ?, ?, ?, ?, ?, ?)"
|
||||||
)
|
)
|
||||||
statement?.setString(1, data.Date_Time)
|
statement?.setString(1, data.Date_Time)
|
||||||
statement?.setString(2, data.Source)
|
statement?.setString(2, data.Source)
|
||||||
@@ -1191,7 +1191,7 @@ class MariaDB(
|
|||||||
statement?.setString(8, data.Language)
|
statement?.setString(8, data.Language)
|
||||||
val rowsAffected = statement?.executeUpdate()
|
val rowsAffected = statement?.executeUpdate()
|
||||||
if (rowsAffected != null && rowsAffected > 0) {
|
if (rowsAffected != null && rowsAffected > 0) {
|
||||||
Logger.info("QueueTable added: ${data.Message}" as Any)
|
Logger.info("QueueTable added Source=${data.Source} Type=${data.Type} Message=${data.Message}, Languages=${data.Language} Variables=${data.SB_TAGS}, BroadcastZones=${data.BroadcastZones}" as Any)
|
||||||
return true
|
return true
|
||||||
} else {
|
} else {
|
||||||
Logger.warn("No QueueTable entry added for: ${data.Message}" as Any)
|
Logger.warn("No QueueTable entry added for: ${data.Message}" as Any)
|
||||||
@@ -1206,7 +1206,7 @@ class MariaDB(
|
|||||||
try {
|
try {
|
||||||
connection.autoCommit = false
|
connection.autoCommit = false
|
||||||
val sql =
|
val sql =
|
||||||
"INSERT INTO ${super.dbName} (Date_Time, Source, Type, Message, SB_TAGS, BroadcastZones, Repeat, Language) VALUES (?, ?, ?, ?, ?, ?, ?, ?)"
|
"INSERT INTO ${super.dbName} (`Date_Time`, `Source`, `Type`, `Message`, `SB_TAGS`, `BroadcastZones`, `Repeat`, `Language`) VALUES (?, ?, ?, ?, ?, ?, ?, ?)"
|
||||||
val statement = connection.prepareStatement(sql)
|
val statement = connection.prepareStatement(sql)
|
||||||
for (qt in data) {
|
for (qt in data) {
|
||||||
statement.setString(1, qt.Date_Time)
|
statement.setString(1, qt.Date_Time)
|
||||||
|
|||||||
Reference in New Issue
Block a user