Commit 25/09/2025
This commit is contained in:
315
src/Main.kt
315
src/Main.kt
@@ -2,17 +2,20 @@ import audio.AudioPlayer
|
|||||||
import barix.BarixConnection
|
import barix.BarixConnection
|
||||||
import barix.TCP_Barix_Command_Server
|
import barix.TCP_Barix_Command_Server
|
||||||
import codes.Somecodes.Companion.Get_ANN_ID
|
import codes.Somecodes.Companion.Get_ANN_ID
|
||||||
|
import codes.Somecodes.Companion.IsAlphabethic
|
||||||
|
import codes.Somecodes.Companion.IsNumber
|
||||||
import codes.Somecodes.Companion.ValidFile
|
import codes.Somecodes.Companion.ValidFile
|
||||||
|
import codes.Somecodes.Companion.ValidString
|
||||||
import codes.Somecodes.Companion.dateformat1
|
import codes.Somecodes.Companion.dateformat1
|
||||||
import codes.Somecodes.Companion.timeformat2
|
import codes.Somecodes.Companion.timeformat2
|
||||||
import com.sun.jna.Platform
|
import com.sun.jna.Platform
|
||||||
|
import content.Category
|
||||||
import content.ContentCache
|
import content.ContentCache
|
||||||
import content.Language
|
import content.Language
|
||||||
import content.ScheduleDay
|
import content.ScheduleDay
|
||||||
import content.VoiceType
|
import content.VoiceType
|
||||||
import database.MariaDB
|
import database.MariaDB
|
||||||
import database.Messagebank
|
import database.Messagebank
|
||||||
import database.QueuePaging
|
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
@@ -24,18 +27,19 @@ import web.WebApp
|
|||||||
import java.time.DayOfWeek
|
import java.time.DayOfWeek
|
||||||
import java.time.LocalDate
|
import java.time.LocalDate
|
||||||
import java.time.LocalTime
|
import java.time.LocalTime
|
||||||
|
import java.util.function.Consumer
|
||||||
import kotlin.concurrent.fixedRateTimer
|
import kotlin.concurrent.fixedRateTimer
|
||||||
|
|
||||||
|
|
||||||
fun main() {
|
fun main() {
|
||||||
val version = "0.0.1 (23/09/2025)"
|
val version = "0.0.1 (23/09/2025)"
|
||||||
val StreamerOutputs : MutableMap<String, BarixConnection> = HashMap()
|
val StreamerOutputs: MutableMap<String, BarixConnection> = HashMap()
|
||||||
|
|
||||||
if (Platform.isWindows()) {
|
if (Platform.isWindows()) {
|
||||||
// supaya OSHI bisa mendapatkan CPU usage di Windows seperti di Task Manager
|
// supaya OSHI bisa mendapatkan CPU usage di Windows seperti di Task Manager
|
||||||
GlobalConfig.set(GlobalConfig.OSHI_OS_WINDOWS_CPU_UTILITY, true)
|
GlobalConfig.set(GlobalConfig.OSHI_OS_WINDOWS_CPU_UTILITY, true)
|
||||||
}
|
}
|
||||||
Logger.info{"Starting AAS New Generation version $version"}
|
Logger.info { "Starting AAS New Generation version $version" }
|
||||||
val audioPlayer = AudioPlayer(44100) // 44100 Hz sampling rate
|
val audioPlayer = AudioPlayer(44100) // 44100 Hz sampling rate
|
||||||
audioPlayer.InitAudio(1)
|
audioPlayer.InitAudio(1)
|
||||||
val content = ContentCache()
|
val content = ContentCache()
|
||||||
@@ -49,19 +53,19 @@ fun main() {
|
|||||||
* @return true jika semua valid, false jika ada yang tidak valid
|
* @return true jika semua valid, false jika ada yang tidak valid
|
||||||
*/
|
*/
|
||||||
fun AllBroadcastZonesValid(bz: List<String>): Boolean {
|
fun AllBroadcastZonesValid(bz: List<String>): Boolean {
|
||||||
if (bz.isNotEmpty()){
|
if (bz.isNotEmpty()) {
|
||||||
val validchannels = bz
|
val validchannels = bz
|
||||||
// check apakah tiap zone ada di database broadcast zones
|
// check apakah tiap zone ada di database broadcast zones
|
||||||
.filter {
|
.filter { z1 ->
|
||||||
z1 -> db.BroadcastZoneList.find { z2 -> z2.SoundChannel==z1 } != null
|
db.BroadcastZoneList.find { z2 -> z2.SoundChannel == z1 } != null
|
||||||
}
|
}
|
||||||
// check apakah tiap zone ada di SoundChannelList dan Online
|
// check apakah tiap zone ada di SoundChannelList dan Online
|
||||||
.filter {
|
.filter { z3 ->
|
||||||
z3 -> StreamerOutputs.any { sc -> sc.value.channel==z3 && sc.value.isOnline() }
|
StreamerOutputs.any { sc -> sc.value.channel == z3 && sc.value.isOnline() }
|
||||||
}
|
}
|
||||||
|
|
||||||
// kalau jumlah valid channel sama dengan jumlah broadcast zone, berarti semua valid
|
// kalau jumlah valid channel sama dengan jumlah broadcast zone, berarti semua valid
|
||||||
return validchannels.size==bz.size
|
return validchannels.size == bz.size
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@@ -72,9 +76,9 @@ fun main() {
|
|||||||
* @return true jika semua idle, false jika ada yang tidak idle
|
* @return true jika semua idle, false jika ada yang tidak idle
|
||||||
*/
|
*/
|
||||||
fun AllBroadcastZoneIdle(bz: List<String>): Boolean {
|
fun AllBroadcastZoneIdle(bz: List<String>): Boolean {
|
||||||
if (bz.isNotEmpty()){
|
if (bz.isNotEmpty()) {
|
||||||
return bz.all {
|
return bz.all { z1 ->
|
||||||
z1 -> StreamerOutputs.any { sc -> sc.value.channel==z1 && sc.value.isIdle() }
|
StreamerOutputs.any { sc -> sc.value.channel == z1 && sc.value.isIdle() }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
@@ -96,88 +100,258 @@ fun main() {
|
|||||||
/**
|
/**
|
||||||
* Fungsi untuk ambil messagebank berdasarkan ANN_ID, diurutkan berdasarkan urutan bahasa di urutan_bahasa
|
* Fungsi untuk ambil messagebank berdasarkan ANN_ID, diurutkan berdasarkan urutan bahasa di urutan_bahasa
|
||||||
* @param id ANN_ID dari messagebank
|
* @param id ANN_ID dari messagebank
|
||||||
|
* @param languages List of language yang diinginkan, default urutan_bahasa
|
||||||
* @return List of Messagebank
|
* @return List of Messagebank
|
||||||
*/
|
*/
|
||||||
fun Get_MessageBank_by_id(id: Int) : ArrayList<Messagebank>{
|
fun Get_MessageBank_by_id(id: Int, languages: List<String> = urutan_bahasa): ArrayList<Messagebank> {
|
||||||
val mb_list = ArrayList<Messagebank>()
|
val mb_list = ArrayList<Messagebank>()
|
||||||
urutan_bahasa.forEach {
|
languages.forEach { lang ->
|
||||||
lang -> db.MessagebankList.find { mb -> mb.ANN_ID==id.toUInt() && mb.Language==lang && mb.Voice_Type==selected_voice }?.let {
|
db.MessagebankList.find { mb -> mb.ANN_ID == id.toUInt() && mb.Language == lang && mb.Voice_Type == selected_voice }
|
||||||
mb_list.add(it)
|
?.let {
|
||||||
}
|
mb_list.add(it)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return mb_list
|
return mb_list
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find soundbank files from messagebank tags, filtered by VoiceType and Language
|
||||||
|
* @param mb Messagebank object
|
||||||
|
* @param variables Map of variables to replace in tags.
|
||||||
|
* @param cbOK Callback function if success, returns List of soundbank file names
|
||||||
|
* @param cbFail Callback function if fail, returns error message
|
||||||
|
*/
|
||||||
|
fun Get_Soundbank_Files(
|
||||||
|
mb: Messagebank,
|
||||||
|
variables: Map<String, String>,
|
||||||
|
cbOK: Consumer<List<String>>,
|
||||||
|
cbFail: Consumer<String>
|
||||||
|
) {
|
||||||
|
val tags = mb.Message_TAGS.split(" ")
|
||||||
|
if (tags.isEmpty()) {
|
||||||
|
cbFail.accept("No tags found in messagebank id ${mb.ANN_ID}")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// dapatkan soundbank array berdasarkan VoiceType dan Language
|
||||||
|
val sb = db.SoundbankList
|
||||||
|
.filter { it.VoiceType == mb.Voice_Type }
|
||||||
|
.filter { it.Language == mb.Language }
|
||||||
|
if (sb.isEmpty()) {
|
||||||
|
cbFail.accept("No soundbank found for voice type ${mb.Voice_Type} and language ${mb.Language}")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
val files = mutableListOf<String>()
|
||||||
|
|
||||||
|
tags.forEach { tag ->
|
||||||
|
val _tag = tag.trim()
|
||||||
|
when (_tag) {
|
||||||
|
"[AIRPLANE_NAME]" -> {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
"[FLIGHT_NUMBER]" -> {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
"[PLATNOMOR]" -> {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
"[CITY]" -> {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
"[PLACES]" -> {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
"[ETAD]" -> {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
"[SHALAT]" -> {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
"[BCB]" -> {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
"[GATENUMBER]" -> {
|
||||||
|
// gate number bisa angka saja, misalnya 1,2,3
|
||||||
|
// atau huruf dan angka, misalnya A1, B2, C3, 1A, 2B, 3C
|
||||||
|
val value = variables["GATENUMBER"].orEmpty()
|
||||||
|
if (ValidString(value)) {
|
||||||
|
val values = value.split(",").map { it.trim() }.filter { ValidString(it) }
|
||||||
|
if (values.isNotEmpty()){
|
||||||
|
values.forEach {
|
||||||
|
if (IsNumber(it)){
|
||||||
|
// gate number hanya angka
|
||||||
|
} else {
|
||||||
|
// gate number gabungan huruf dan angka
|
||||||
|
val regex = Regex("([A-Z])?(\\d+)([A-Z])?")
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
cbFail.accept("GATENUMBER variable is empty after split for tag $_tag in messagebank id ${mb.ANN_ID}")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
cbFail.accept("GATENUMBER variable is missing or empty for tag $_tag in messagebank id ${mb.ANN_ID}")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
"[REASON]" -> {
|
||||||
|
val reason = sb.firstOrNull { it.Category == Category.Reason.name && it.TAG == _tag }
|
||||||
|
if (reason != null) {
|
||||||
|
if (ValidFile(reason.Path)) {
|
||||||
|
files.add(reason.Path)
|
||||||
|
} else {
|
||||||
|
cbFail.accept("Invalid soundbank file ${reason.Path} for tag=$_tag voicetype=${mb.Voice_Type} language=${mb.Language} ANN_ID=${mb.ANN_ID}")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
cbFail.accept("No Reason found for tag=$_tag voicetype=${mb.Voice_Type} language=${mb.Language} ANN_ID=${mb.ANN_ID}")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
"[PROCEDURE]" -> {
|
||||||
|
val procedure = sb.firstOrNull { it.Category == Category.Procedure.name && it.TAG == _tag }
|
||||||
|
if (procedure != null) {
|
||||||
|
if (ValidFile(procedure.Path)) {
|
||||||
|
files.add(procedure.Path)
|
||||||
|
} else {
|
||||||
|
cbFail.accept("Invalid soundbank file ${procedure.Path} for tag=$_tag voicetype=${mb.Voice_Type} language=${mb.Language} ANN_ID=${mb.ANN_ID}")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
cbFail.accept("No Procedure found for tag=$_tag voicetype=${mb.Voice_Type} language=${mb.Language} ANN_ID=${mb.ANN_ID}")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else -> {
|
||||||
|
// Phrase
|
||||||
|
val phrase = sb.firstOrNull { it.Category == Category.Phrase.name && it.TAG == _tag }
|
||||||
|
if (phrase != null) {
|
||||||
|
if (ValidFile(phrase.Path)) {
|
||||||
|
files.add(phrase.Path)
|
||||||
|
} else {
|
||||||
|
cbFail.accept("Invalid soundbank file ${phrase.Path} for tag=$_tag voicetype=${mb.Voice_Type} language=${mb.Language} ANN_ID=${mb.ANN_ID}")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
cbFail.accept("No Phrase found for tag=$_tag voicetype=${mb.Voice_Type} language=${mb.Language} ANN_ID=${mb.ANN_ID}")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
jobloop@ while (isActive) {
|
jobloop@ while (isActive) {
|
||||||
delay(1000)
|
delay(1000)
|
||||||
|
|
||||||
// prioritas 1 , habisin queue paging
|
// prioritas 1 , habisin queue paging
|
||||||
for(it in db.Read_Queue_Paging()){
|
for (qp in db.Read_Queue_Paging()) {
|
||||||
if (it.BroadcastZones.isNotBlank()){
|
if (qp.BroadcastZones.isNotBlank()) {
|
||||||
val zz = it.BroadcastZones.split(";")
|
val zz = qp.BroadcastZones.split(";")
|
||||||
if (AllBroadcastZonesValid(zz)){
|
if (AllBroadcastZonesValid(zz)) {
|
||||||
if (AllBroadcastZoneIdle(zz)){
|
if (AllBroadcastZoneIdle(zz)) {
|
||||||
if (it.Source=="PAGING"){
|
if (qp.Source == "PAGING") {
|
||||||
// nama file ada di Message
|
// nama file ada di Message
|
||||||
if (ValidFile(it.Message)){
|
if (ValidFile(qp.Message)) {
|
||||||
val afi = audioPlayer.LoadAudioFile(it.Message)
|
val afi = audioPlayer.LoadAudioFile(qp.Message)
|
||||||
zz.forEach {
|
zz.forEach { z1 ->
|
||||||
z1 -> StreamerOutputs.values.find { it.channel==z1 }?.SendData(afi.bytes, {db.Add_Log("AAS", it) }, {db.Add_Log("AAS", it)} )
|
StreamerOutputs.values.find { it.channel == z1 }
|
||||||
|
?.SendData(afi.bytes, { db.Add_Log("AAS", it) }, { db.Add_Log("AAS", it) })
|
||||||
}
|
}
|
||||||
val logmessage = "Broadcast started PAGING with Filename '${it.Message}' to zones: ${it.BroadcastZones}"
|
val logmessage =
|
||||||
Logger.info { logmessage}
|
"Broadcast started PAGING with Filename '${qp.Message}' to zones: ${qp.BroadcastZones}"
|
||||||
|
Logger.info { logmessage }
|
||||||
db.Add_Log("AAS", logmessage)
|
db.Add_Log("AAS", logmessage)
|
||||||
db.Delete_Queue_Paging_by_index(it.index)
|
db.Delete_Queue_Paging_by_index(qp.index)
|
||||||
|
|
||||||
continue@jobloop
|
continue@jobloop
|
||||||
} else {
|
} else {
|
||||||
// file tidak valid, delete from queue paging
|
// file tidak valid, delete from queue paging
|
||||||
db.Delete_Queue_Paging_by_index(it.index)
|
db.Delete_Queue_Paging_by_index(qp.index)
|
||||||
db.Add_Log("AAS", "Cancelled paging message with index ${it.index} due to invalid audio file" )
|
db.Add_Log(
|
||||||
|
"AAS",
|
||||||
|
"Cancelled paging message with index ${qp.index} due to invalid audio file"
|
||||||
|
)
|
||||||
}
|
}
|
||||||
} else if (it.Source=="SHALAT"){
|
} else if (qp.Source == "SHALAT") {
|
||||||
val ann_id = Get_ANN_ID(it.Message)
|
val ann_id = Get_ANN_ID(qp.Message)
|
||||||
if (ann_id>0){
|
if (ann_id > 0) {
|
||||||
Get_MessageBank_by_id(ann_id).forEach {
|
// shalat, ambil messagebank berdasarkan ann_id dengan bahasa Indonesia saja
|
||||||
// cari tags nya, create content nya, broadcast ke semua zone
|
Get_MessageBank_by_id(ann_id, listOf(Language.INDONESIA.name)).let { mblist ->
|
||||||
|
if (mblist.isNotEmpty()) {
|
||||||
|
//TODO find soundbank
|
||||||
|
} else {
|
||||||
|
// tidak ada messagebank dengan ann_id ini, delete from queue paging
|
||||||
|
db.Delete_Queue_Paging_by_index(qp.index)
|
||||||
|
db.Add_Log(
|
||||||
|
"AAS",
|
||||||
|
"Cancelled Shalat message with index ${qp.index} due to ANN_ID $ann_id not found in Messagebank"
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else{
|
} else {
|
||||||
// invalid ann_id, delete from queue paging
|
// invalid ann_id, delete from queue paging
|
||||||
db.Delete_Queue_Paging_by_index(it.index)
|
db.Delete_Queue_Paging_by_index(qp.index)
|
||||||
db.Add_Log("AAS", "Cancelled Shalat message with index ${it.index} due to invalid ANN_ID" )
|
db.Add_Log(
|
||||||
|
"AAS",
|
||||||
|
"Cancelled Shalat message with index ${qp.index} due to invalid ANN_ID"
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} 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(qp.index)
|
||||||
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 ${qp.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(qp.index)
|
||||||
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 ${qp.index} due to empty broadcast zone")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// prioritas 2, habisin queue table
|
// prioritas 2, habisin queue table
|
||||||
db.Read_Queue_Table().forEach {
|
db.Read_Queue_Table().forEach {
|
||||||
if (it.BroadcastZones.isNotEmpty()){
|
if (it.BroadcastZones.isNotEmpty()) {
|
||||||
val zz = it.BroadcastZones.split(";")
|
val zz = it.BroadcastZones.split(";")
|
||||||
if (AllBroadcastZonesValid(zz)){
|
if (AllBroadcastZonesValid(zz)) {
|
||||||
if (AllBroadcastZoneIdle(zz)){
|
if (AllBroadcastZoneIdle(zz)) {
|
||||||
if (it.Type=="SOUNDBANK"){
|
if (it.Type == "SOUNDBANK") {
|
||||||
|
|
||||||
} else if (it.Type=="TIMER"){
|
} else if (it.Type == "TIMER") {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
} 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)
|
||||||
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
|
||||||
@@ -195,10 +369,10 @@ fun main() {
|
|||||||
delay(1000)
|
delay(1000)
|
||||||
val localtime = LocalTime.now()
|
val localtime = LocalTime.now()
|
||||||
// detik harus 00
|
// detik harus 00
|
||||||
if (localtime.second!=0) continue
|
if (localtime.second != 0) continue
|
||||||
val timestring = timeformat2.format(localtime)
|
val timestring = timeformat2.format(localtime)
|
||||||
val sch = db.SchedulebankList.filter{
|
val sch = db.SchedulebankList.filter {
|
||||||
it.Time==timestring && it.Enable
|
it.Time == timestring && it.Enable
|
||||||
}
|
}
|
||||||
// tidak ada schedule dengan time sekarang dan enable=true
|
// tidak ada schedule dengan time sekarang dan enable=true
|
||||||
if (sch.isEmpty()) continue
|
if (sch.isEmpty()) continue
|
||||||
@@ -207,15 +381,15 @@ fun main() {
|
|||||||
val ddmmyyyy = dateformat1.format(localdate)
|
val ddmmyyyy = dateformat1.format(localdate)
|
||||||
// check special date dulu
|
// check special date dulu
|
||||||
val specialdate = sch.find {
|
val specialdate = sch.find {
|
||||||
it.Day==ddmmyyyy
|
it.Day == ddmmyyyy
|
||||||
}
|
}
|
||||||
if (specialdate!=null) {
|
if (specialdate != null) {
|
||||||
// TODO Masukin ke queue table sebagai schedule special date
|
// TODO Masukin ke queue table sebagai schedule special date
|
||||||
|
|
||||||
}
|
}
|
||||||
// cek weekly schedule
|
// cek weekly schedule
|
||||||
val weekly = sch.find {
|
val weekly = sch.find {
|
||||||
it.Day == when(localdate.dayOfWeek){
|
it.Day == when (localdate.dayOfWeek) {
|
||||||
DayOfWeek.MONDAY -> ScheduleDay.Monday.name
|
DayOfWeek.MONDAY -> ScheduleDay.Monday.name
|
||||||
DayOfWeek.TUESDAY -> ScheduleDay.Tuesday.name
|
DayOfWeek.TUESDAY -> ScheduleDay.Tuesday.name
|
||||||
DayOfWeek.WEDNESDAY -> ScheduleDay.Wednesday.name
|
DayOfWeek.WEDNESDAY -> ScheduleDay.Wednesday.name
|
||||||
@@ -225,7 +399,7 @@ fun main() {
|
|||||||
DayOfWeek.SUNDAY -> ScheduleDay.Sunday.name
|
DayOfWeek.SUNDAY -> ScheduleDay.Sunday.name
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (weekly!=null) {
|
if (weekly != null) {
|
||||||
// TODO Masukin ke queue table sebagai schedule weekly
|
// TODO Masukin ke queue table sebagai schedule weekly
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -233,13 +407,12 @@ fun main() {
|
|||||||
val daily = sch.find {
|
val daily = sch.find {
|
||||||
it.Day == ScheduleDay.Everyday.name
|
it.Day == ScheduleDay.Everyday.name
|
||||||
}
|
}
|
||||||
if (daily!=null) {
|
if (daily != null) {
|
||||||
// TODO Masukin ke queue table sebagai schedule daily
|
// TODO Masukin ke queue table sebagai schedule daily
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -252,16 +425,16 @@ fun main() {
|
|||||||
)
|
)
|
||||||
web.Start()
|
web.Start()
|
||||||
|
|
||||||
val barixserver = TCP_Barix_Command_Server ()
|
val barixserver = TCP_Barix_Command_Server()
|
||||||
barixserver.StartTcpServer { cmd ->
|
barixserver.StartTcpServer { cmd ->
|
||||||
Logger.info{cmd}
|
Logger.info { cmd }
|
||||||
val _streamer = StreamerOutputs[cmd.ipaddress]
|
val _streamer = StreamerOutputs[cmd.ipaddress]
|
||||||
val _sc = db.SoundChannelList.find { it.ip == cmd.ipaddress }
|
val _sc = db.SoundChannelList.find { it.ip == cmd.ipaddress }
|
||||||
if (_streamer==null){
|
if (_streamer == null) {
|
||||||
// belum create BarixConnection untuk ipaddress ini
|
// belum create BarixConnection untuk ipaddress ini
|
||||||
Logger.info{"New Streamer Output connection from ${cmd.ipaddress}"}
|
Logger.info { "New Streamer Output connection from ${cmd.ipaddress}" }
|
||||||
if (_sc!=null){
|
if (_sc != null) {
|
||||||
val _bc = BarixConnection(_sc.index,_sc.channel,cmd.ipaddress)
|
val _bc = BarixConnection(_sc.index, _sc.channel, cmd.ipaddress)
|
||||||
_bc.vu = cmd.vu
|
_bc.vu = cmd.vu
|
||||||
_bc.bufferRemain = cmd.buffremain
|
_bc.bufferRemain = cmd.buffremain
|
||||||
_bc.statusData = cmd.statusdata
|
_bc.statusData = cmd.statusdata
|
||||||
@@ -270,7 +443,7 @@ fun main() {
|
|||||||
|
|
||||||
} else {
|
} else {
|
||||||
// sudah ada, update data
|
// sudah ada, update data
|
||||||
if (_sc !=null && _sc.channel != _streamer.channel) {
|
if (_sc != null && _sc.channel != _streamer.channel) {
|
||||||
_streamer.channel = _sc.channel
|
_streamer.channel = _sc.channel
|
||||||
}
|
}
|
||||||
_streamer.vu = cmd.vu
|
_streamer.vu = cmd.vu
|
||||||
@@ -280,7 +453,7 @@ fun main() {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
val onlinechecker = fixedRateTimer(name="onlinecheck", initialDelay = 1000, period = 1000) {
|
val onlinechecker = fixedRateTimer(name = "onlinecheck", initialDelay = 1000, period = 1000) {
|
||||||
// cek setiap 1 detik, decrement online counter semua BarixConnection
|
// cek setiap 1 detik, decrement online counter semua BarixConnection
|
||||||
StreamerOutputs.values.forEach {
|
StreamerOutputs.values.forEach {
|
||||||
it.decrementOnlineCounter()
|
it.decrementOnlineCounter()
|
||||||
@@ -289,14 +462,14 @@ fun main() {
|
|||||||
|
|
||||||
// shutdown hook
|
// shutdown hook
|
||||||
Runtime.getRuntime().addShutdownHook(Thread {
|
Runtime.getRuntime().addShutdownHook(Thread {
|
||||||
Logger.info{"Shutdown hook called, stopping services..."}
|
Logger.info { "Shutdown hook called, stopping services..." }
|
||||||
barixserver.StopTcpCommand()
|
barixserver.StopTcpCommand()
|
||||||
onlinechecker.cancel()
|
onlinechecker.cancel()
|
||||||
web.Stop()
|
web.Stop()
|
||||||
audioPlayer.Close()
|
audioPlayer.Close()
|
||||||
db.close()
|
db.close()
|
||||||
Logger.info{"All services stopped, exiting application."}
|
Logger.info { "All services stopped, exiting application." }
|
||||||
} )
|
})
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,6 +38,20 @@ class Somecodes {
|
|||||||
// regex for getting ann_id from Message, which is the number inside []
|
// regex for getting ann_id from Message, which is the number inside []
|
||||||
private val ann_id_regex = Regex("\\[(\\d+)]")
|
private val ann_id_regex = Regex("\\[(\\d+)]")
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if a string is a valid number.
|
||||||
|
*/
|
||||||
|
fun IsNumber(value: String) : Boolean {
|
||||||
|
return value.toIntOrNull() != null
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if a string is alphabetic (contains only letters).
|
||||||
|
*/
|
||||||
|
fun IsAlphabethic(value: String) : Boolean {
|
||||||
|
return value.all { it.isLetter() }
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extract ANN ID from a message string.
|
* Extract ANN ID from a message string.
|
||||||
* The ANN ID is expected to be a number enclosed in square brackets (e.g., "[123]").
|
* The ANN ID is expected to be a number enclosed in square brackets (e.g., "[123]").
|
||||||
|
|||||||
@@ -11,5 +11,7 @@ enum class Category(name: String) {
|
|||||||
PlatNomor("PlatNomor"),
|
PlatNomor("PlatNomor"),
|
||||||
Shalat("Shalat"),
|
Shalat("Shalat"),
|
||||||
Year("Year"),
|
Year("Year"),
|
||||||
Birthday("Birthday");
|
Birthday("Birthday"),
|
||||||
|
Reason("Reason"),
|
||||||
|
Procedure("Procedure");
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user