116 lines
4.5 KiB
Kotlin
116 lines
4.5 KiB
Kotlin
package barix
|
|
|
|
import codes.Somecodes.Companion.ValidString
|
|
import kotlinx.coroutines.*
|
|
import org.tinylog.Logger
|
|
import java.net.ServerSocket
|
|
import java.net.Socket
|
|
import java.util.function.Consumer
|
|
|
|
@Suppress("unused")
|
|
class TCP_Barix_Command_Server {
|
|
lateinit var tcpserver: ServerSocket
|
|
lateinit var job: Job
|
|
private val socketMap = mutableMapOf<String, Socket>()
|
|
|
|
private val regex = """STATUSBARIX;(\d+);(\d+);?(\d)?"""
|
|
private val pattern = Regex(regex)
|
|
|
|
/**
|
|
* Start TCP Command Server
|
|
* @param port The port number to listen on (default is 5001)
|
|
* @param cb A callback function that will be called when a valid command is received
|
|
* @return true if successful
|
|
*/
|
|
fun StartTcpServer(port: Int = 5001, cb: Consumer<BarixStatus>): Boolean {
|
|
try {
|
|
val tcp = ServerSocket(port)
|
|
tcpserver = tcp
|
|
job = CoroutineScope(Dispatchers.IO).launch {
|
|
Logger.info { "TCP StreamerOutput server started on port $port" }
|
|
while (isActive) {
|
|
if (tcpserver.isClosed) break
|
|
try {
|
|
|
|
val socket = tcpserver.accept()
|
|
CoroutineScope(Dispatchers.IO).launch {
|
|
val key : String = socket.inetAddress.hostAddress
|
|
socketMap[key] = socket
|
|
Logger.info { "Start communicating with Streamer Output with IP : $key" }
|
|
val din = socket.getInputStream()
|
|
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)
|
|
if (ValidString(str)) {
|
|
// Valid command from Barix is in format $"STATUSBARIX;VU;BuffRemain;StatusData"$
|
|
pattern.find(str)?.let { matchResult ->
|
|
val (vu, buffremain, statusdata) = matchResult.destructured
|
|
val status = BarixStatus(
|
|
socket.inetAddress.hostAddress,
|
|
vu.toInt(),
|
|
buffremain.toInt(),
|
|
statusdata.toIntOrNull() ?: 0
|
|
)
|
|
//Logger.info { "Received valid command from $key : $status" }
|
|
cb.accept(status)
|
|
} ?: run {
|
|
Logger.warn { "Invalid command format from $key : $str" }
|
|
}
|
|
}
|
|
}
|
|
}
|
|
Logger.info { "Finished communicating with Streamer Output with IP $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}" }
|
|
}
|
|
return false
|
|
}
|
|
|
|
/**
|
|
* Get Socket by IP address
|
|
* @param ip The IP address of the client
|
|
* @return Socket if found, null otherwise
|
|
*/
|
|
fun getSocket(ip: String): Socket? {
|
|
return socketMap[ip]
|
|
}
|
|
|
|
|
|
} |