diff --git a/.gitignore b/.gitignore index 5c642fb..d9b9fde 100644 --- a/.gitignore +++ b/.gitignore @@ -32,6 +32,7 @@ bin/ .DS_Store ## Soundbank directories ## -/PagingResult/ -/SoundBanks/ -/SoundbankResult/ \ No newline at end of file +PagingResult/ +SoundBank/ +SoundbankResult/ +logs/ \ No newline at end of file diff --git a/.idea/libraries/github_oshi_core.xml b/.idea/libraries/github_oshi_core.xml index c264d5f..cb9598b 100644 --- a/.idea/libraries/github_oshi_core.xml +++ b/.idea/libraries/github_oshi_core.xml @@ -1,11 +1,11 @@ - + - - - - + + + + diff --git a/.idea/libraries/net_java_dev_jna.xml b/.idea/libraries/net_java_dev_jna.xml index f946aa2..60a85e6 100644 --- a/.idea/libraries/net_java_dev_jna.xml +++ b/.idea/libraries/net_java_dev_jna.xml @@ -1,8 +1,8 @@ - + - + diff --git a/.idea/libraries/tinylog_impl.xml b/.idea/libraries/tinylog_impl.xml index 4d4ee78..2483189 100644 --- a/.idea/libraries/tinylog_impl.xml +++ b/.idea/libraries/tinylog_impl.xml @@ -1,9 +1,9 @@ - + - - + + diff --git a/src/Main.kt b/src/Main.kt index c2e4293..c2ee700 100644 --- a/src/Main.kt +++ b/src/Main.kt @@ -16,6 +16,7 @@ import kotlinx.coroutines.delay import kotlinx.coroutines.isActive import kotlinx.coroutines.launch import org.tinylog.Logger +import org.tinylog.provider.ProviderRegistry import oshi.util.GlobalConfig import web.WebApp import java.nio.file.Files @@ -148,7 +149,7 @@ fun main() { val _sc = db.soundchannelDB.List.find { it.ip == cmd.ipaddress } if (_streamer == null) { // 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) { val _bc = BarixConnection(_sc.index, _sc.channel, cmd.ipaddress) _bc.vu = cmd.vu @@ -188,6 +189,7 @@ fun main() { audioPlayer.Close() db.close() Logger.info { "All services stopped, exiting application." } + ProviderRegistry.getLoggingProvider().shutdown() }) diff --git a/src/barix/BarixConnection.kt b/src/barix/BarixConnection.kt index 6fc6839..0a91ad1 100644 --- a/src/barix/BarixConnection.kt +++ b/src/barix/BarixConnection.kt @@ -100,10 +100,10 @@ class BarixConnection(val index: UInt, var channel: String, val ipaddress: Strin val chunk = ByteArray(if (bb.remaining() > maxUDPsize) maxUDPsize else bb.remaining()) bb.get(chunk) while(bufferRemain = si.hardware.networkIFs.toList() + //TODO cari network yang sesuai dengan networkname +// networks.forEach { net -> +// +// println(net.name+" "+net.displayName+" ") +// net.updateAttributes() +// println("upload: ${SizetoHuman(net.bytesSent)} sent, download: ${SizetoHuman(net.bytesRecv)} received") +// } + return "" + } + /** * Check if a value is a valid non-blank string. * @param value The value to check. diff --git a/src/commandServer/TCP_Android_Command_Server.kt b/src/commandServer/TCP_Android_Command_Server.kt index 1ecbc91..2329f31 100644 --- a/src/commandServer/TCP_Android_Command_Server.kt +++ b/src/commandServer/TCP_Android_Command_Server.kt @@ -50,42 +50,40 @@ class TCP_Android_Command_Server { while (isActive) { if (tcpserver.isClosed) break try { - tcpserver.accept().use { socket -> - { - CoroutineScope(Dispatchers.IO).launch { - if (socket != null) { - // key is IP address only - val key: String = socket.inetAddress.hostAddress - socketMap[key] = socket - Logger.info { "Start communicating with $key" } - socket.getInputStream().let { 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("@").map { it.trim() }.filter { ValidString(it) } - .map { it.uppercase() }.forEach { - process_command(key,it) { reply -> - try { - socket.getOutputStream().write(String_to_Byte_Android(reply)) - } catch (e: Exception) { - logcb.accept("Failed to send reply to $key, Message : ${e.message}") - } - } - } + val socket = tcpserver.accept() + + CoroutineScope(Dispatchers.IO).launch { + if (socket != null) { + // key is IP address only + val key: String = socket.inetAddress.hostAddress + socketMap[key] = socket + Logger.info { "Start communicating with IPMT/IPM with IP $key" } + val din = socket.getInputStream() + val dout = socket.getOutputStream() + 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) + println("Received from $key : $str") + str.split("@").map { it.trim() }.filter { ValidString(it) } + .forEach { + process_command(key,it) { reply -> + try { + println("Reply to $key : ${reply.length} bytes") + dout.write(String_to_Byte_Android(reply)) + } catch (e: Exception) { + logcb.accept("Failed to send reply to $key, Message : $e") } } } - } - logcb.accept("Finished communicatiing with $key") - socketMap.remove(key) } - } + logcb.accept("Finished communicatiing with $key") + socketMap.remove(key) } + } } catch (ex: Exception) { @@ -109,8 +107,8 @@ class TCP_Android_Command_Server { */ private fun String_to_Byte_Android(str: String): ByteArray { if (ValidString(str)) { - val len = str.length - val bytes = str.toByteArray() + val bytes = str.toByteArray(Charsets.UTF_8) + val len = bytes.size return ByteBuffer.allocate(len + 4) .order(ByteOrder.LITTLE_ENDIAN) .putInt(len) @@ -128,14 +126,15 @@ class TCP_Android_Command_Server { */ private fun process_command(key: String, cmd: String, cb: Consumer) { Logger.info { "Command from $key : $cmd" } - val parts = cmd.split(";").map { it.trim() }.filter { it.isNotBlank() }.map { it.uppercase() } + val parts = cmd.split(";").map { it.trim() }.filter { it.isNotBlank() } when (parts[0]) { "GETLOGIN" -> { // Android login request val username = parts.getOrElse(1) { "" } val password = parts.getOrElse(2) { "" } if (ValidString(username) && ValidString(password)) { - if (db.userDB.List.any{it.username==username && it.password==password}) { + if (db.userDB.List.any{ + it.username==username && it.password==password}) { val existing = listUserLogin.find { it.ip == key} if (existing!=null){ existing.username = username @@ -236,10 +235,14 @@ class TCP_Android_Command_Server { // pengiriman variabel ke Android val username = parts.getOrElse(1) { "" } if (ValidString(username)){ + println("Initialize request from $key with username $username") val userlogin = listUserLogin.find { it.username == username } if (userlogin != null){ + println("User $username found in listUserLogin") val userdb = db.userDB.List.find { it.username == username } if (userdb != null){ + println("User $username found in userDB") + println(userdb) val result = StringBuilder() result.append("ZONE") userdb.broadcastzones.split(";").map { it.trim() }.filter { it.isNotBlank() }.forEach { @@ -268,56 +271,59 @@ class TCP_Android_Command_Server { result.append("MSGTOTAL;").append(VARMESSAGES.size).append("@") // VAR AP TOTAL val VARAPTOTAL = mutableListOf() - val sb_split = userdb.soundbank_tags.split(";").map { it.trim() }.filter { it.isNotBlank() } - sb_split.forEach { + 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() - sb_split.forEach { + 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() - sb_split.forEach { - val sb = db.Find_Soundbank_Places(it).firstOrNull() - if (sb != null) VARPLACESTOTAL.add(sb) - } +// 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() - sb_split.forEach { - val sb = db.Find_Soundbank_Shalat(it).firstOrNull() - if (sb != null) VARSHALATTOTAL.add(sb) - } +// 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() - sb_split.forEach { - val sb = db.Find_Soundbank_Sequence(it).firstOrNull() - if (sb != null) VARSEQUENCETOTAL.add(sb) - } +// sb_split.forEach { +// val sb = db.Find_Soundbank_Sequence(it).firstOrNull() +// if (sb != null) VARSEQUENCETOTAL.add(sb) +// } // VAR REASON TOTAL val VARREASONTOTAL = mutableListOf() - sb_split.forEach { - val sb = db.Find_Soundbank_Reason(it).firstOrNull() - if (sb != null) VARREASONTOTAL.add(sb) - } +// 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() - sb_split.forEach { - val sb = db.Find_Soundbank_Procedure(it).firstOrNull() - if (sb != null) VARPROCEDURETOTAL.add(sb) - } +// 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()) + println("Result so far: $result") + println("Result size: ${result.length} bytes") result.clear() //Append MSG, for Android only Indonesia and English @@ -359,6 +365,8 @@ class TCP_Android_Command_Server { result.append("VARPROCEDURE;").append(index).append(";").append(soundbank.TAG).append(";").append(soundbank.Description).append("@") } // send to sender + println("Final Result: $result") + println("Final Result size: ${result.length} bytes") cb.accept(result.toString()) logcb.accept("All variables sent to $key with username $username") diff --git a/src/database/MariaDB.kt b/src/database/MariaDB.kt index 0bb4dee..34a66cb 100644 --- a/src/database/MariaDB.kt +++ b/src/database/MariaDB.kt @@ -1840,7 +1840,8 @@ class MariaDB( "username VARCHAR(100) NOT NULL," + "password VARCHAR(100) NOT NULL," + "location VARCHAR(100) NOT NULL," + - "soundbank_tags TEXT NOT NULL,"+ // Comma-separated soundbank tags + "airline_tags TEXT NOT NULL,"+ // Comma-separated soundbank tags + "city_tags TEXT NOT NULL,"+ // Comma-separated soundbank tags "messagebank_ann_id TEXT NOT NULL,"+ // Comma-separated messagebank announcement index "broadcastzones TEXT NOT NULL"+ // Comma-separated broadcast zones ")" @@ -1858,7 +1859,8 @@ class MariaDB( resultSet.getString("username"), resultSet.getString("password"), resultSet.getString("location"), - resultSet.getString("soundbank_tags"), + resultSet.getString("airline_tags"), + resultSet.getString("city_tags"), resultSet.getString("messagebank_ann_id"), resultSet.getString("broadcastzones") ) @@ -1872,13 +1874,14 @@ class MariaDB( override fun Add(data: UserDB): Boolean { try { - val statement = connection.prepareStatement("INSERT INTO ${super.dbName} (username, password, location, soundbank_tags, messagebank_ann_id, broadcastzones) VALUES (?, ?, ?, ?, ?, ?)") + val statement = connection.prepareStatement("INSERT INTO ${super.dbName} (username, password, location, airline_tags, city_tags, messagebank_ann_id, broadcastzones) VALUES (?, ?, ?, ?,?, ?, ?)") statement?.setString(1, data.username) statement?.setString(2, data.password) statement?.setString(3, data.location) - statement?.setString(4, data.soundbank_tags) - statement?.setString(5, data.messagebank_ann_id) - statement?.setString(6, data.broadcastzones) + statement?.setString(4, data.airline_tags) + statement?.setString(5, data.city_tags) + statement?.setString(6, data.messagebank_ann_id) + statement?.setString(7, data.broadcastzones) val rowsAffected = statement?.executeUpdate() if (rowsAffected != null && rowsAffected > 0) { Logger.info("User added: ${data.username}" as Any) @@ -1895,15 +1898,16 @@ class MariaDB( override fun AddAll(data: ArrayList): Boolean { return try { connection.autoCommit = false - val sql = "INSERT INTO ${super.dbName} (username, password, location,soundbank_tags, messagebank_ann_id, broadcastzones) VALUES (?, ?, ?, ?, ?, ?)" + val sql = "INSERT INTO ${super.dbName} (username, password, location,airline_tags,city_tags, messagebank_ann_id, broadcastzones) VALUES (?, ?, ?,?, ?, ?, ?)" val statement = connection.prepareStatement(sql) for (user in data) { statement.setString(1, user.username) statement.setString(2, user.password) statement.setString(3, user.location) - statement.setString(4, user.soundbank_tags) - statement.setString(5, user.messagebank_ann_id) - statement.setString(6, user.broadcastzones) + statement.setString(4, user.airline_tags) + statement.setString(5, user.city_tags) + statement.setString(6, user.messagebank_ann_id) + statement.setString(7, user.broadcastzones) statement.addBatch() } statement.executeBatch() @@ -1919,14 +1923,15 @@ class MariaDB( override fun UpdateByIndex(index: Int, data: UserDB): Boolean { try { - val statement = connection.prepareStatement("UPDATE ${super.dbName} SET username = ?, password = ?, location = ?, soundbank_tags = ?, messagebank_ann_id = ?, broadcastzones = ? WHERE `index` = ?") + val statement = connection.prepareStatement("UPDATE ${super.dbName} SET username = ?, password = ?, location = ?, airline_tags = ?,city_tags=?, messagebank_ann_id = ?, broadcastzones = ? WHERE `index` = ?") statement?.setString(1, data.username) statement?.setString(2, data.password) statement?.setString(3, data.location) - statement?.setString(4, data.soundbank_tags) - statement?.setString(5, data.messagebank_ann_id) - statement?.setString(6, data.broadcastzones) - statement?.setLong(7, index.toLong()) + statement?.setString(4, data.airline_tags) + statement?.setString(5, data.city_tags) + statement?.setString(6, data.messagebank_ann_id) + statement?.setString(7, data.broadcastzones) + statement?.setLong(8, index.toLong()) val rowsAffected = statement?.executeUpdate() if (rowsAffected != null && rowsAffected > 0) { Logger.info("User updated at index $index: ${data.username}" as Any) @@ -1963,7 +1968,7 @@ class MariaDB( try { val sheet = workbook.getSheet("User") ?: throw Exception("No sheet named 'User' found") val headerRow = sheet.getRow(0) ?: throw Exception("No header row found") - val headers = arrayOf("Index", "username", "password", "location", "soundbank_tags", "messagebank_ann_id", "broadcastzones") + val headers = arrayOf("Index", "username", "password", "location", "airline_tags", "city_tags", "messagebank_ann_id", "broadcastzones") for ((colIndex, header) in headers.withIndex()) { val cell = headerRow.getCell(colIndex) ?: throw Exception("Header '$header' not found") if (cell.stringCellValue != header) throw Exception("Header '$header' not found") @@ -1977,10 +1982,11 @@ class MariaDB( val username = row.getCell(1)?.stringCellValue ?: continue val password = row.getCell(2)?.stringCellValue ?: continue val location = row.getCell(3)?.stringCellValue ?: continue - val soundbank_tags = row.getCell(4)?.stringCellValue ?: continue - val messagebank_ann_id = row.getCell(5)?.stringCellValue ?: continue - val broadcastzones = row.getCell(6)?.stringCellValue ?: continue - val user = UserDB(0u, username, password, location, soundbank_tags, messagebank_ann_id, broadcastzones) + val airline_tags = row.getCell(4)?.stringCellValue ?: continue + val city_tags = row.getCell(5)?.stringCellValue ?: continue + val messagebank_ann_id = row.getCell(6)?.stringCellValue ?: continue + val broadcastzones = row.getCell(7)?.stringCellValue ?: continue + val user = UserDB(0u, username, password, location, airline_tags,city_tags, messagebank_ann_id, broadcastzones) _userList.add(user) } return AddAll(_userList) @@ -1997,7 +2003,7 @@ class MariaDB( val workbook = XSSFWorkbook() val sheet = workbook.createSheet("User") val headerRow = sheet.createRow(0) - val headers = arrayOf("Index", "username", "password", "location", "soundbank_tags", "messagebank_ann_id", "broadcastzones") + val headers = arrayOf("Index", "username", "password", "location", "airline_tags","city_tags", "messagebank_ann_id", "broadcastzones") for ((colIndex, header) in headers.withIndex()) { val cell = headerRow.createCell(colIndex) cell.setCellValue(header) @@ -2009,9 +2015,10 @@ class MariaDB( row.createCell(1).setCellValue(resultSet.getString("username")) row.createCell(2).setCellValue(resultSet.getString("password")) row.createCell(3).setCellValue(resultSet.getString("location")) - row.createCell(4).setCellValue(resultSet.getString("soundbank_tags")) - row.createCell(5).setCellValue(resultSet.getString("messagebank_ann_id")) - row.createCell(6).setCellValue(resultSet.getString("broadcastzones")) + row.createCell(4).setCellValue(resultSet.getString("airline_tags")) + row.createCell(5).setCellValue(resultSet.getString("city_tags")) + row.createCell(6).setCellValue(resultSet.getString("messagebank_ann_id")) + row.createCell(7).setCellValue(resultSet.getString("broadcastzones")) } for (i in headers.indices) { sheet.autoSizeColumn(i) diff --git a/src/database/UserDB.kt b/src/database/UserDB.kt index 58e9a5d..bf02d86 100644 --- a/src/database/UserDB.kt +++ b/src/database/UserDB.kt @@ -1,4 +1,11 @@ package database @Suppress("unused") -data class UserDB(var index: UInt, var username: String, var password: String, var location: String, var soundbank_tags: String, var messagebank_ann_id: String, var broadcastzones: String) +data class UserDB(var index: UInt, var username: String, var password: String, var location: String, var airline_tags: String, var city_tags: String, var messagebank_ann_id: String, var broadcastzones: String){ + override fun toString(): String { + return "UserDB(index=$index, username='$username', location='$location', airline_tags='$airline_tags', city_tags='$city_tags', messagebank_ann_id='$messagebank_ann_id', broadcastzones='$broadcastzones')" + } +} + + + diff --git a/src/simplelogger.properties b/src/simplelogger.properties new file mode 100644 index 0000000..dd35ce8 --- /dev/null +++ b/src/simplelogger.properties @@ -0,0 +1,2 @@ +# gak mau lihat log javalin +org.slf4j.simpleLogger.defaultLogLevel=error diff --git a/src/tinylog.properties b/src/tinylog.properties new file mode 100644 index 0000000..02167e2 --- /dev/null +++ b/src/tinylog.properties @@ -0,0 +1,10 @@ +writer1 = console +writer1.level = info +writer1.format = {date:dd/MM/yyyy HH:mm:ss} {class}.{method}(): {message} + +writer2 = rolling file +writer2.format = {date:dd/MM/yyyy HH:mm:ss} {class}.{method}(): {message} +writer2.file = logs/{date:yyyy}/{date:MM}/{date:dd}.log +writer2.level = info + +autoshutdown = false # optional, default: true \ No newline at end of file diff --git a/src/web/WebApp.kt b/src/web/WebApp.kt index c95a358..6cedfde 100644 --- a/src/web/WebApp.kt +++ b/src/web/WebApp.kt @@ -52,6 +52,7 @@ class WebApp(val listenPort: Int, val userlist: List>) { } fun Start() { + app = Javalin.create { config -> config.useVirtualThreads = true config.staticFiles.add("/webpage") @@ -125,6 +126,7 @@ class WebApp(val listenPort: Int, val userlist: List>) { "getNetworkStatus" -> { // TODO Get Network status + Somecodes.GetNetworkStatus("") SendReply(wsMessageContext, cmd.command, "OK") }