commit 03/09/2025
This commit is contained in:
73
src/Main.kt
73
src/Main.kt
@@ -1,6 +1,9 @@
|
|||||||
import audio.AudioPlayer
|
import audio.AudioPlayer
|
||||||
|
import codes.Somecodes.Companion.dateformat1
|
||||||
|
import codes.Somecodes.Companion.timeformat2
|
||||||
import com.sun.jna.Platform
|
import com.sun.jna.Platform
|
||||||
import content.ContentCache
|
import content.ContentCache
|
||||||
|
import content.ScheduleDay
|
||||||
import database.MariaDB
|
import database.MariaDB
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
@@ -10,6 +13,9 @@ import kotlinx.coroutines.launch
|
|||||||
import org.tinylog.Logger
|
import org.tinylog.Logger
|
||||||
import oshi.util.GlobalConfig
|
import oshi.util.GlobalConfig
|
||||||
import web.WebApp
|
import web.WebApp
|
||||||
|
import java.time.DayOfWeek
|
||||||
|
import java.time.LocalDate
|
||||||
|
import java.time.LocalTime
|
||||||
|
|
||||||
|
|
||||||
fun main() {
|
fun main() {
|
||||||
@@ -22,6 +28,7 @@ fun main() {
|
|||||||
audioPlayer.InitAudio(1)
|
audioPlayer.InitAudio(1)
|
||||||
val content = ContentCache()
|
val content = ContentCache()
|
||||||
val db = MariaDB()
|
val db = MariaDB()
|
||||||
|
// Coroutine untuk cek Paging Queue dan AAS Queue setiap detik
|
||||||
CoroutineScope(Dispatchers.Default).launch {
|
CoroutineScope(Dispatchers.Default).launch {
|
||||||
while (isActive) {
|
while (isActive) {
|
||||||
delay(1000)
|
delay(1000)
|
||||||
@@ -38,16 +45,12 @@ fun main() {
|
|||||||
} else {
|
} else {
|
||||||
// ada broadcast zone yang tidak valid, delete from queue paging
|
// ada broadcast zone yang tidak valid, delete from queue paging
|
||||||
db.Delete_Queue_Paging_by_index(it.index)
|
db.Delete_Queue_Paging_by_index(it.index)
|
||||||
//TODO check log message yang benar
|
db.Add_Log("AAS", "Cancelled paging message with index ${it.index} due to invalid broadcast zone"
|
||||||
db.Add_Log(
|
|
||||||
"AAS",
|
|
||||||
"Cancelled paging message with index ${it.index} due to invalid broadcast zone"
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// invalid broadcast zone, delete from queue paging
|
// invalid broadcast zone, delete from queue paging
|
||||||
db.Delete_Queue_Paging_by_index(it.index)
|
db.Delete_Queue_Paging_by_index(it.index)
|
||||||
// TODO check log message yang benar
|
|
||||||
db.Add_Log("AAS", "Cancelled paging message with index ${it.index} due to empty broadcast zone")
|
db.Add_Log("AAS", "Cancelled paging message with index ${it.index} due to empty broadcast zone")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -62,22 +65,72 @@ fun main() {
|
|||||||
} else {
|
} else {
|
||||||
// ada broadcast zone yang tidak valid, delete from queue table
|
// ada broadcast zone yang tidak valid, delete from queue table
|
||||||
db.Delete_Queue_Table_by_index(it.index)
|
db.Delete_Queue_Table_by_index(it.index)
|
||||||
//TODO check log message yang benar
|
db.Add_Log("AAS", "Cancelled table message with index ${it.index} due to invalid broadcast zone"
|
||||||
db.Add_Log(
|
|
||||||
"AAS",
|
|
||||||
"Cancelled table message with index ${it.index} due to invalid broadcast zone"
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// invalid broadcast zone, delete from queue table
|
// invalid broadcast zone, delete from queue table
|
||||||
db.Delete_Queue_Table_by_index(it.index)
|
db.Delete_Queue_Table_by_index(it.index)
|
||||||
// TODO check log message yang benar
|
|
||||||
db.Add_Log("AAS", "Cancelled table message with index ${it.index} due to empty broadcast zone")
|
db.Add_Log("AAS", "Cancelled table message with index ${it.index} due to empty broadcast zone")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
// Coroutine untuk cek Schedulebank tiap menit saat detik 00
|
||||||
|
CoroutineScope(Dispatchers.Default).launch {
|
||||||
|
while (isActive) {
|
||||||
|
delay(1000)
|
||||||
|
val localtime = LocalTime.now()
|
||||||
|
// detik harus 00
|
||||||
|
if (localtime.second!=0) continue
|
||||||
|
val timestring = timeformat2.format(localtime)
|
||||||
|
val sch = db.SchedulebankList.filter{
|
||||||
|
it.Time==timestring && it.Enable
|
||||||
|
}
|
||||||
|
// tidak ada schedule dengan time sekarang dan enable=true
|
||||||
|
if (sch.isEmpty()) continue
|
||||||
|
|
||||||
|
val localdate = LocalDate.now()
|
||||||
|
val ddmmyyyy = dateformat1.format(localdate)
|
||||||
|
// check special date dulu
|
||||||
|
val specialdate = sch.find {
|
||||||
|
it.Day==ddmmyyyy
|
||||||
|
}
|
||||||
|
if (specialdate!=null) {
|
||||||
|
// TODO Masukin ke queue table sebagai schedule special date
|
||||||
|
|
||||||
|
}
|
||||||
|
// cek weekly schedule
|
||||||
|
val weekly = sch.find {
|
||||||
|
it.Day == when(localdate.dayOfWeek){
|
||||||
|
DayOfWeek.MONDAY -> ScheduleDay.Monday.name
|
||||||
|
DayOfWeek.TUESDAY -> ScheduleDay.Tuesday.name
|
||||||
|
DayOfWeek.WEDNESDAY -> ScheduleDay.Wednesday.name
|
||||||
|
DayOfWeek.THURSDAY -> ScheduleDay.Thursday.name
|
||||||
|
DayOfWeek.FRIDAY -> ScheduleDay.Friday.name
|
||||||
|
DayOfWeek.SATURDAY -> ScheduleDay.Saturday.name
|
||||||
|
DayOfWeek.SUNDAY -> ScheduleDay.Sunday.name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (weekly!=null) {
|
||||||
|
// TODO Masukin ke queue table sebagai schedule weekly
|
||||||
|
|
||||||
|
}
|
||||||
|
// check daily schedule
|
||||||
|
val daily = sch.find {
|
||||||
|
it.Day == ScheduleDay.Everyday.name
|
||||||
|
}
|
||||||
|
if (daily!=null) {
|
||||||
|
// TODO Masukin ke queue table sebagai schedule daily
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
val web = WebApp(
|
val web = WebApp(
|
||||||
3030,
|
3030,
|
||||||
listOf(
|
listOf(
|
||||||
|
|||||||
105
src/commandServer/TCP_Android_Command_Server.kt
Normal file
105
src/commandServer/TCP_Android_Command_Server.kt
Normal file
@@ -0,0 +1,105 @@
|
|||||||
|
package commandServer
|
||||||
|
|
||||||
|
import codes.Somecodes.Companion.ValidString
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.Job
|
||||||
|
import kotlinx.coroutines.isActive
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import kotlinx.coroutines.runBlocking
|
||||||
|
import org.tinylog.Logger
|
||||||
|
import java.net.ServerSocket
|
||||||
|
import java.net.Socket
|
||||||
|
import java.util.function.Consumer
|
||||||
|
|
||||||
|
@Suppress("unused")
|
||||||
|
class TCP_Android_Command_Server {
|
||||||
|
private var tcpserver: ServerSocket? = null
|
||||||
|
private var job: Job? = null
|
||||||
|
private val socketMap = mutableMapOf<String, Socket>()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Start TCP Command Server
|
||||||
|
* @param port The port to listen on, default is 5003
|
||||||
|
* @param cb The callback function to handle incoming messages
|
||||||
|
* @return true if successful
|
||||||
|
*/
|
||||||
|
fun StartTcpServer(port: Int = 5003, cb: Consumer<String>): Boolean {
|
||||||
|
try {
|
||||||
|
val tcp = ServerSocket(port)
|
||||||
|
tcpserver = tcp
|
||||||
|
job = CoroutineScope(Dispatchers.IO).launch {
|
||||||
|
Logger.info { "TCP server started" }
|
||||||
|
while (isActive) {
|
||||||
|
if (tcpserver?.isClosed == true) break
|
||||||
|
try {
|
||||||
|
tcpserver?.accept().use { socket ->
|
||||||
|
{
|
||||||
|
CoroutineScope(Dispatchers.Main).launch {
|
||||||
|
if (socket != null) {
|
||||||
|
val key : String = socket.inetAddress.hostAddress+":"+socket.port
|
||||||
|
socketMap[key] = socket
|
||||||
|
Logger.info { "Start communicating with $key" }
|
||||||
|
socket.getInputStream().use { din ->
|
||||||
|
{
|
||||||
|
while (isActive) {
|
||||||
|
if (din.available()>0){
|
||||||
|
val bb = ByteArray(din.available())
|
||||||
|
din.read(bb)
|
||||||
|
// B4A format, 4 bytes di depan adalah size
|
||||||
|
val str = String(bb,4,bb.size-4)
|
||||||
|
str.split("@").forEach {
|
||||||
|
if (ValidString(it)){
|
||||||
|
cb.accept(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Logger.info { "Finished communicating with $key" }
|
||||||
|
socketMap.remove(key)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (ex: Exception) {
|
||||||
|
Logger.error { "Failed accepting TCP Socket, Message : ${ex.message}" }
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
Logger.info { "TCP server stopped" }
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Logger.error { "Failed to StartTcpServer, Message : ${e.message}" }
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stop TCP Command Server
|
||||||
|
* @return true if succesful
|
||||||
|
*/
|
||||||
|
fun StopTcpCommand(): Boolean {
|
||||||
|
try {
|
||||||
|
tcpserver?.close()
|
||||||
|
runBlocking {
|
||||||
|
socketMap.values.forEach {
|
||||||
|
it.close()
|
||||||
|
}
|
||||||
|
socketMap.clear()
|
||||||
|
job?.join()
|
||||||
|
}
|
||||||
|
Logger.info { "StopTcpCommand success" }
|
||||||
|
return true
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Logger.error { "Failed to StopTcpServer, Message : ${e.message}" }
|
||||||
|
} finally {
|
||||||
|
tcpserver = null
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
101
src/commandServer/TCP_PC_Command_Server.kt
Normal file
101
src/commandServer/TCP_PC_Command_Server.kt
Normal file
@@ -0,0 +1,101 @@
|
|||||||
|
package commandServer
|
||||||
|
|
||||||
|
import codes.Somecodes.Companion.ValidString
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.Job
|
||||||
|
import kotlinx.coroutines.isActive
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import kotlinx.coroutines.runBlocking
|
||||||
|
import org.tinylog.Logger
|
||||||
|
import java.net.ServerSocket
|
||||||
|
import java.net.Socket
|
||||||
|
import java.util.function.Consumer
|
||||||
|
|
||||||
|
@Suppress("unused")
|
||||||
|
class TCP_PC_Command_Server {
|
||||||
|
private var tcpserver: ServerSocket? = null
|
||||||
|
private var job: Job? = null
|
||||||
|
private val socketMap = mutableMapOf<String, Socket>()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Start TCP Command Server
|
||||||
|
* @param port The port number to listen on (default is 5000)
|
||||||
|
* @param cb A callback function that will be called when a valid command is received
|
||||||
|
* @return true if successful
|
||||||
|
*/
|
||||||
|
fun StartTcpServer(port: Int = 5000, cb: Consumer<String>): Boolean {
|
||||||
|
try {
|
||||||
|
val tcp = ServerSocket(port)
|
||||||
|
tcpserver = tcp
|
||||||
|
job = CoroutineScope(Dispatchers.IO).launch {
|
||||||
|
Logger.info { "TCP server started" }
|
||||||
|
while (isActive) {
|
||||||
|
if (tcpserver?.isClosed == true) break
|
||||||
|
try {
|
||||||
|
tcpserver?.accept().use { socket ->
|
||||||
|
{
|
||||||
|
CoroutineScope(Dispatchers.Main).launch {
|
||||||
|
if (socket != null) {
|
||||||
|
val key : String = socket.inetAddress.hostAddress+":"+socket.port
|
||||||
|
socketMap[key] = socket
|
||||||
|
Logger.info { "Start communicating with $key" }
|
||||||
|
socket.getInputStream().use { din ->
|
||||||
|
{
|
||||||
|
while (isActive) {
|
||||||
|
if (din.available()>0){
|
||||||
|
val bb = ByteArray(din.available())
|
||||||
|
din.read(bb)
|
||||||
|
// B4A format, 4 bytes di depan adalah size
|
||||||
|
val str = String(bb)
|
||||||
|
if (ValidString(str)) cb.accept(str)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Logger.info { "Finished communicating with $key" }
|
||||||
|
socketMap.remove(key)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (ex: Exception) {
|
||||||
|
Logger.error { "Failed accepting TCP Socket, Message : ${ex.message}" }
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
Logger.info { "TCP server stopped" }
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Logger.error { "Failed to StartTcpServer, Message : ${e.message}" }
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stop TCP Command Server
|
||||||
|
* @return true if succesful
|
||||||
|
*/
|
||||||
|
fun StopTcpCommand(): Boolean {
|
||||||
|
try {
|
||||||
|
tcpserver?.close()
|
||||||
|
runBlocking {
|
||||||
|
socketMap.values.forEach {
|
||||||
|
it.close()
|
||||||
|
}
|
||||||
|
socketMap.clear()
|
||||||
|
job?.join()
|
||||||
|
}
|
||||||
|
Logger.info { "StopTcpCommand success" }
|
||||||
|
return true
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Logger.error { "Failed to StopTcpServer, Message : ${e.message}" }
|
||||||
|
} finally {
|
||||||
|
tcpserver = null
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1247,7 +1247,7 @@ class MariaDB(
|
|||||||
* Reads all entries from the queue_table in the database.
|
* Reads all entries from the queue_table in the database.
|
||||||
* @return A list of QueueTable entries.
|
* @return A list of QueueTable entries.
|
||||||
*/
|
*/
|
||||||
fun Read_Queue_Table(): List<QueueTable> {
|
fun Read_Queue_Table(): ArrayList<QueueTable> {
|
||||||
val queueList = ArrayList<QueueTable>()
|
val queueList = ArrayList<QueueTable>()
|
||||||
try {
|
try {
|
||||||
val statement = connection?.createStatement()
|
val statement = connection?.createStatement()
|
||||||
@@ -1314,7 +1314,7 @@ class MariaDB(
|
|||||||
* Reads all entries from the queue_paging in the database.
|
* Reads all entries from the queue_paging in the database.
|
||||||
* @return A list of QueuePaging entries.
|
* @return A list of QueuePaging entries.
|
||||||
*/
|
*/
|
||||||
fun Read_Queue_Paging(): List<QueuePaging> {
|
fun Read_Queue_Paging(): ArrayList<QueuePaging> {
|
||||||
val queueList = ArrayList<QueuePaging>()
|
val queueList = ArrayList<QueuePaging>()
|
||||||
try {
|
try {
|
||||||
val statement = connection?.createStatement()
|
val statement = connection?.createStatement()
|
||||||
|
|||||||
@@ -119,40 +119,12 @@ class WebApp(val listenPort: Int, val userlist: List<Pair<String, String>>, val
|
|||||||
SendReply(wsMessageContext, cmd.command, "OK")
|
SendReply(wsMessageContext, cmd.command, "OK")
|
||||||
}
|
}
|
||||||
|
|
||||||
"getSoundBankList" -> {
|
"getPagingQueue" ->{
|
||||||
println("getSoundBankList command received")
|
SendReply(wsMessageContext, cmd.command, MariaDB.ArrayListtoString(db.Read_Queue_Paging()))
|
||||||
SendReply(
|
|
||||||
wsMessageContext,
|
|
||||||
cmd.command,
|
|
||||||
MariaDB.ArrayListtoString(db.SoundbankList)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
"getMessageBankList" -> {
|
"getAASPagingQueue" ->{
|
||||||
println("getMessageBankList command received")
|
SendReply(wsMessageContext, cmd.command, MariaDB.ArrayListtoString(db.Read_Queue_Table()))
|
||||||
SendReply(
|
|
||||||
wsMessageContext,
|
|
||||||
cmd.command,
|
|
||||||
MariaDB.ArrayListtoString(db.MessagebankList)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
"getLanguageList" -> {
|
|
||||||
println("getLanguageList command received")
|
|
||||||
SendReply(
|
|
||||||
wsMessageContext,
|
|
||||||
cmd.command,
|
|
||||||
MariaDB.ArrayListtoString(db.LanguageLinkList)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
"getTimerList" -> {
|
|
||||||
println("getTimerList command received")
|
|
||||||
SendReply(
|
|
||||||
wsMessageContext,
|
|
||||||
cmd.command,
|
|
||||||
MariaDB.ArrayListtoString(db.SchedulebankList)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
else -> {
|
else -> {
|
||||||
@@ -718,6 +690,29 @@ class WebApp(val listenPort: Int, val userlist: List<Pair<String, String>>, val
|
|||||||
}
|
}
|
||||||
} else get1.status(400).result("Invalid logdate")
|
} else get1.status(400).result("Invalid logdate")
|
||||||
}
|
}
|
||||||
|
get("ExportXLSX/<logdate>/<logfilter>") { get1 ->
|
||||||
|
val logdate = get1.pathParam("logdate")
|
||||||
|
val logfilter = get1.pathParam("logfilter")
|
||||||
|
if (ValidDate(logdate)) {
|
||||||
|
val xlsxdata = if (ValidString(logfilter)) {
|
||||||
|
db.Export_Log_XLSX(logdate, logfilter)
|
||||||
|
} else {
|
||||||
|
db.Export_Log_XLSX(logdate, "")
|
||||||
|
}
|
||||||
|
if (xlsxdata != null) {
|
||||||
|
get1.header(
|
||||||
|
"Content-Type",
|
||||||
|
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
|
||||||
|
)
|
||||||
|
get1.header("Content-Disposition", "attachment; filename=\"log_$logdate.xlsx\"")
|
||||||
|
get1.outputStream().use { out ->
|
||||||
|
xlsxdata.write(out)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
get1.status(500).result("Failed to export log to XLSX")
|
||||||
|
}
|
||||||
|
} else get1.status(400).result("Invalid logdate")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user