diff --git a/html/webpage/assets/js/script.js b/html/webpage/assets/js/script.js index 7f0b14a..d293996 100644 --- a/html/webpage/assets/js/script.js +++ b/html/webpage/assets/js/script.js @@ -339,7 +339,17 @@ $(document).ready(function () { $('#diskstatus').text("Disk : " + data) break; case "getNetworkStatus": - $('#networkstatus').text("Network : " + data) + //console.log("Network status: ", data); + let result = ""; + let json = JSON.parse(data); + if (Array.isArray(json) && json.length> 0){ + json.forEach((net)=>{ + //console.log("Network interface: ", net); + if (result.length>0) result+="\n" + result+=`${net.displayName} (${net.ipV4addr.join(";")}) TX:${(net.txSpeed/1024).toFixed(1)} KB/s RX:${(net.rxSpeed/1024).toFixed(1)} KB/s; ` + }) + } else result = "N/A"; + $('#networkstatus').text(result) break; case "getSystemTime": $('#datetimetext').text(data) diff --git a/src/Main.kt b/src/Main.kt index 8707c7c..220e7b4 100644 --- a/src/Main.kt +++ b/src/Main.kt @@ -31,7 +31,7 @@ lateinit var audioPlayer: AudioPlayer val StreamerOutputs: MutableMap = HashMap() lateinit var udpreceiver: UDPReceiver lateinit var tcpreceiver: TCPReceiver -const val version = "0.0.6 (14/10/2025)" +const val version = "0.0.7 (15/10/2025)" // AAS 64 channels const val max_channel = 64 diff --git a/src/codes/Somecodes.kt b/src/codes/Somecodes.kt index a62121c..8795e2c 100644 --- a/src/codes/Somecodes.kt +++ b/src/codes/Somecodes.kt @@ -4,6 +4,7 @@ import com.fasterxml.jackson.databind.JsonNode import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper import content.Category import content.Language +import content.NetworkInformation import content.ScheduleDay import content.VoiceType import kotlinx.coroutines.CoroutineScope @@ -35,6 +36,7 @@ class Somecodes { val si = SystemInfo() val processor: CentralProcessor = si.hardware.processor val memory : GlobalMemory = si.hardware.memory + val NetworkInfoMap = mutableMapOf() val datetimeformat1: DateTimeFormatter = DateTimeFormatter.ofPattern("dd/MM/yyyy HH:mm:ss") val dateformat1: DateTimeFormatter = DateTimeFormatter.ofPattern("dd/MM/yyyy") @@ -278,16 +280,43 @@ class Somecodes { , (usedMemory.toDouble() / totalMemory * 100)) } - fun GetNetworkStatus(networkname: String) : String{ + fun GetNetworkStatus(cb : Consumer>) { val networks: List = 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 "" + networks.forEach { net -> + + if (net.ifOperStatus==NetworkIF.IfOperStatus.UP){ + if (net.iPv4addr.size>0 || net.iPv6addr.size>0){ + var ni = NetworkInfoMap[net.name] + if (ni == null){ + ni = NetworkInformation(net.name, net.displayName, net.macaddr) + NetworkInfoMap[net.name] = ni + } + ni.ipV4addr = net.iPv4addr.toMutableList() + ni.ipV6addr = net.iPv6addr.toMutableList() + ni.speed = net.speed + ni.packetsSent = net.packetsSent + ni.packetsRecv = net.packetsRecv + if (ni.updateStamp==0L){ + ni.bytesSent = net.bytesSent + ni.bytesRecv = net.bytesRecv + ni.txSpeed = 0 + ni.rxSpeed = 0 + ni.updateStamp = System.currentTimeMillis() + } else { + // tx speed = (current bytesSent - previous bytesSent) / (current time - previous time) * 1000 + val currentTime = System.currentTimeMillis() + ni.txSpeed = ((net.bytesSent - ni.bytesSent) * 1000 / (currentTime - ni.updateStamp)) + ni.rxSpeed = ((net.bytesRecv - ni.bytesRecv) * 1000 / (currentTime - ni.updateStamp)) + ni.bytesSent = net.bytesSent + ni.bytesRecv = net.bytesRecv + ni.updateStamp = currentTime + } + } else if (NetworkInfoMap.contains(net.name)) NetworkInfoMap.remove(net.name) + } else if (NetworkInfoMap.contains(net.name)) NetworkInfoMap.remove(net.name) + + + } + cb.accept(NetworkInfoMap.values.toList()) } /** diff --git a/src/content/NetworkInformation.kt b/src/content/NetworkInformation.kt new file mode 100644 index 0000000..916a858 --- /dev/null +++ b/src/content/NetworkInformation.kt @@ -0,0 +1,15 @@ +package content + +class NetworkInformation(val name: String, val displayName: String, val macAddress: String) { + var ipV4addr: MutableList = mutableListOf() + var ipV6addr: MutableList = mutableListOf() + var bytesSent: Long = 0 + var bytesRecv: Long = 0 + var packetsSent: Long = 0 + var packetsRecv: Long = 0 + var speed: Long = 0 // in bits per second + var updateStamp : Long = 0 // epoch time in milliseconds, buat hitung speed + var txSpeed: Long = 0 + var rxSpeed: Long = 0 + +} \ No newline at end of file diff --git a/src/database/BroadcastZones.kt b/src/database/BroadcastZones.kt index b766d3c..cf2529c 100644 --- a/src/database/BroadcastZones.kt +++ b/src/database/BroadcastZones.kt @@ -1,4 +1,28 @@ package database @Suppress("unused") -data class BroadcastZones(var index: UInt, var description: String, var SoundChannel: String, var id: String, var bp: String) +data class BroadcastZones(var index: UInt, var description: String, var SoundChannel: String, var id: String, var bp: String){ + + /** + * Check if all fields are not empty + */ + fun isNotEmpty(): Boolean{ + if (description.isNotEmpty()){ + if (SoundChannel.isNotEmpty()){ + if (id.isNotEmpty()){ + if (bp.isNotEmpty()){ + return true + } + } + } + } + return false + } + + /** + * Return a string representation of the BroadcastZones object. + */ + override fun toString(): String { + return "BroadcastZones(index=$index, description='$description', SoundChannel='$SoundChannel', id='$id', bp='$bp')" + } +} diff --git a/src/database/BroadcastZonesHtml.kt b/src/database/BroadcastZonesHtml.kt deleted file mode 100644 index 8bda430..0000000 --- a/src/database/BroadcastZonesHtml.kt +++ /dev/null @@ -1,3 +0,0 @@ -package database - -data class BroadcastZonesHtml(var index: UInt, var description: String, var SoundChannel: String, var Box: String, var Relay: String) diff --git a/src/database/IpZones.kt b/src/database/IpZones.kt deleted file mode 100644 index 7debd6b..0000000 --- a/src/database/IpZones.kt +++ /dev/null @@ -1,4 +0,0 @@ -package database - -@Suppress("unused") -data class IpZones(var index:UInt, var description: String, var ip: String) diff --git a/src/database/LanguageLink.kt b/src/database/LanguageLink.kt index 540b9b4..bea931d 100644 --- a/src/database/LanguageLink.kt +++ b/src/database/LanguageLink.kt @@ -1,4 +1,22 @@ package database -@Suppress("unused") -data class LanguageLink(var index: UInt, var TAG: String, var Language: String) +data class LanguageLink(var index: UInt, var TAG: String, var Language: String){ + + /** + * Check if the LanguageLink object has non-empty TAG and Language fields. + * @return true if both TAG and Language are not empty, false otherwise. + */ + fun isNotEmpty() : Boolean { + return TAG.isNotEmpty() && Language.isNotEmpty() + + } + + /** + * Returns a string representation of the LanguageLink object. + * @return A string in the format "LanguageLink(index=..., TAG='...', Language='...')". + */ + override fun toString(): String { + return "LanguageLink(index=$index, TAG='$TAG', Language='$Language')" + } + +} diff --git a/src/database/LogSemiauto.kt b/src/database/LogSemiauto.kt index 6d24a7b..b3bf8a1 100644 --- a/src/database/LogSemiauto.kt +++ b/src/database/LogSemiauto.kt @@ -1,4 +1,9 @@ package database -@Suppress("unused") -data class LogSemiauto(val index: UInt, val date: String, val time: String, val source: String, val description: String) +data class LogSemiauto(val index: UInt, val date: String, val time: String, val source: String, val description: String){ + + + override fun toString(): String { + return "$date $time [$source] $description" + } +} diff --git a/src/database/Messagebank.kt b/src/database/Messagebank.kt index e3d5fbf..2da8a0c 100644 --- a/src/database/Messagebank.kt +++ b/src/database/Messagebank.kt @@ -8,4 +8,27 @@ data class Messagebank( var Voice_Type: String, var Message_Detail: String, var Message_TAGS: String - ) + ) { + + /** + * Check if all fields are not empty and ANN_ID > 0 + */ + fun isNotEmpty(): Boolean{ + if (Description.isNotEmpty()){ + if (Language.isNotEmpty()){ + if (Voice_Type.isNotEmpty()){ + if (Message_Detail.isNotEmpty()){ + if (Message_TAGS.isNotEmpty()){ + return true + } + } + } + } + } + return false + } + + override fun toString(): String { + return "Messagebank(index=$index, Description='$Description', Language='$Language', ANN_ID=$ANN_ID, Voice_Type='$Voice_Type', Message_Detail='$Message_Detail', Message_TAGS='$Message_TAGS')" + } +} diff --git a/src/database/QueueFids.kt b/src/database/QueueFids.kt index 5711b6c..8c27727 100644 --- a/src/database/QueueFids.kt +++ b/src/database/QueueFids.kt @@ -1,4 +1,13 @@ package database @Suppress("unused") -data class QueueFids(var index: UInt, var ALCODE: String, var FLNUM: String, var ORIGIN: String, var ETAD: String, var FREMARK: String) +data class QueueFids(var index: UInt, var ALCODE: String, var FLNUM: String, var ORIGIN: String, var ETAD: String, var FREMARK: String){ + + fun isNotEmpty(): Boolean { + return ALCODE.isNotEmpty() && FLNUM.isNotEmpty() && ORIGIN.isNotEmpty() && ETAD.isNotEmpty() && FREMARK.isNotEmpty() + } + + override fun toString(): String { + return "QueueFids(index=$index, ALCODE='$ALCODE', FLNUM='$FLNUM', ORIGIN='$ORIGIN', ETAD='$ETAD', FREMARK='$FREMARK')" + } +} diff --git a/src/database/QueuePaging.kt b/src/database/QueuePaging.kt index 38afb29..e26dfa6 100644 --- a/src/database/QueuePaging.kt +++ b/src/database/QueuePaging.kt @@ -1,6 +1,10 @@ package database data class QueuePaging(var index: UInt, var Date_Time: String, var Source: String, var Type: String, var Message: String, var BroadcastZones: String){ + fun isNotEmpty(): Boolean { + return Date_Time.isNotEmpty() && Source.isNotEmpty() && Type.isNotEmpty() && Message.isNotEmpty() && BroadcastZones.isNotEmpty() + } + override fun toString(): String { return "QueuePaging(index=$index, Date_Time='$Date_Time', Source='$Source', Type='$Type', Message='$Message', BroadcastZones='$BroadcastZones')" } diff --git a/src/database/QueueTable.kt b/src/database/QueueTable.kt index e5be756..2aae77f 100644 --- a/src/database/QueueTable.kt +++ b/src/database/QueueTable.kt @@ -2,6 +2,12 @@ package database data class QueueTable(var index: UInt, var Date_Time: String, var Source: String, var Type: String, var Message: String, var SB_TAGS: String, var BroadcastZones: String, var Repeat: UInt, var Language: String){ + /** + * Check if all fields are not empty + */ + fun isNotEmpty(): Boolean { + return Date_Time.isNotEmpty() && Source.isNotEmpty() && Type.isNotEmpty() && Message.isNotEmpty() && SB_TAGS.isNotEmpty() && BroadcastZones.isNotEmpty() && Language.isNotEmpty() + } override fun toString(): String { return "QueueTable(index=$index, Date_Time='$Date_Time', Source='$Source', Type='$Type', Message='$Message', SB_TAGS='$SB_TAGS', BroadcastZones='$BroadcastZones', Repeat=$Repeat, Language='$Language')" } diff --git a/src/database/ScheduleBank.kt b/src/database/ScheduleBank.kt index 300d89e..aa0a6c9 100644 --- a/src/database/ScheduleBank.kt +++ b/src/database/ScheduleBank.kt @@ -10,4 +10,13 @@ data class ScheduleBank( var Repeat: UByte, var Enable: Boolean, var BroadcastZones: String, - var Language: String) + var Language: String) { + + override fun toString(): String { + return "ScheduleBank(index=$index, Description='$Description', Day='$Day', Time='$Time', Soundpath='$Soundpath', Repeat=$Repeat, Enable=$Enable, BroadcastZones='$BroadcastZones', Language='$Language')" + } + + fun isNotEmpty() : Boolean{ + return Description.isNotEmpty() && Day.isNotEmpty() && Time.isNotEmpty() && Soundpath.isNotEmpty() && BroadcastZones.isNotEmpty() && Language.isNotEmpty() + } +} diff --git a/src/database/SoundChannel.kt b/src/database/SoundChannel.kt index 1e95750..6dc3cc3 100644 --- a/src/database/SoundChannel.kt +++ b/src/database/SoundChannel.kt @@ -1,4 +1,17 @@ package database -@Suppress("unused") -data class SoundChannel(val index: UInt, val channel: String, val ip: String) +data class SoundChannel(val index: UInt, val channel: String, val ip: String) { + + + override fun toString(): String { + return "SoundChannel(index=$index, channel='$channel', ip='$ip')" + } + + /** + * Check if both channel and ip are not empty + * @return true if both channel and ip are not empty, false otherwise + */ + fun isNotEmpty() : Boolean { + return channel.isNotEmpty() && ip.isNotEmpty() + } +} diff --git a/src/database/Soundbank.kt b/src/database/Soundbank.kt index 8f38c9f..67366c5 100644 --- a/src/database/Soundbank.kt +++ b/src/database/Soundbank.kt @@ -1,6 +1,5 @@ package database -import content.Category data class Soundbank( var index: UInt, @@ -16,20 +15,7 @@ data class Soundbank( * Check if all fields are not empty */ fun isNotEmpty(): Boolean{ - if (Description.isNotEmpty()){ - if (TAG.isNotEmpty()){ - if (Category.isNotEmpty()){ - if (Language.isNotEmpty()){ - if (VoiceType.isNotEmpty()){ - if (Path.isNotEmpty()){ - return true - } - } - } - } - } - } - return false + return Description.isNotEmpty() && TAG.isNotEmpty() && Category.isNotEmpty() && Language.isNotEmpty() && VoiceType.isNotEmpty() && Path.isNotEmpty() } /** diff --git a/src/database/UserDB.kt b/src/database/UserDB.kt index 991ac35..edc79b3 100644 --- a/src/database/UserDB.kt +++ b/src/database/UserDB.kt @@ -6,6 +6,10 @@ data class UserDB(var index: UInt, var username: String, var password: String, v return "UserDB(index=$index, username='$username', location='$location', airline_tags='$airline_tags', city_tags='$city_tags', messagebank_ann_id='$messagebank_ann_id', broadcastzones='$broadcastzones')" } + fun isNotEmpty() : Boolean { + return username.isNotEmpty() && password.isNotEmpty() && location.isNotEmpty() && airline_tags.isNotEmpty() && city_tags.isNotEmpty() && messagebank_ann_id.isNotEmpty() && broadcastzones.isNotEmpty() + } + /** * Compares this UserDB object with another UserDB object for equality. * Two UserDB objects are considered equal if all their properties are equal, except for the index property. diff --git a/src/web/WebApp.kt b/src/web/WebApp.kt index 0d54ab3..1d4cb5a 100644 --- a/src/web/WebApp.kt +++ b/src/web/WebApp.kt @@ -34,7 +34,6 @@ import io.javalin.apibuilder.ApiBuilder.path import io.javalin.apibuilder.ApiBuilder.post import io.javalin.apibuilder.ApiBuilder.ws import io.javalin.http.Context -import io.javalin.http.servlet.splitKeyValueStringAndGroupByKey import io.javalin.json.JavalinJackson import io.javalin.websocket.WsMessageContext import org.apache.poi.xssf.usermodel.XSSFWorkbook @@ -130,9 +129,9 @@ class WebApp(val listenPort: Int, val userlist: List>) { } "getNetworkStatus" -> { - // TODO Get Network status - Somecodes.GetNetworkStatus("") - SendReply(wsMessageContext, cmd.command, "OK") + Somecodes.GetNetworkStatus { nn -> + SendReply(wsMessageContext, cmd.command, objectmapper.writeValueAsString(nn)) + } } "getPagingQueue" ->{