package barix import codes.Somecodes import com.fasterxml.jackson.databind.JsonNode import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.delay import kotlinx.coroutines.launch import org.tinylog.Logger import java.net.DatagramPacket import java.net.DatagramSocket import java.net.InetSocketAddress import java.net.Socket import java.nio.ByteBuffer import java.util.function.Consumer @Suppress("unused") class BarixConnection(val index: UInt, var channel: String, val ipaddress: String, val port: Int = 5002) { private var _bR: Int = 0 private var _sd: Int = 0 private var _vu: Int = 0 private var _onlinecounter = 0 private val udp = DatagramSocket(0) private val inet = InetSocketAddress(ipaddress, port) private val maxUDPsize = 1000 private var _tcp: Socket? = null /** * Buffer remain in bytes */ var bufferRemain: Int get() = _bR set(value) { _bR = value _onlinecounter = 5 } /** * Status data, 0 = playback idle, 1 = playback running */ var statusData: Int get() = _sd set(value) { _sd = if (value < 0) 0 else if (value > 1) 1 else value _onlinecounter = 5 } /** * VU level 0-100 */ var vu: Int get() = _vu set(value) { _vu = if (value < 0) 0 else if (value > 100) 100 else value _onlinecounter = 5 } /** * TCP command socket for communication with this Barix device */ var commandsocket: Socket? get() = _tcp set(value){ _tcp = value } /** * Decrement online counter, if counter reaches 0, the device is considered offline */ fun decrementOnlineCounter() { if (_onlinecounter > 0) { _onlinecounter-- } } /** * Check if Barix device is online * @return true if online */ fun isOnline(): Boolean { return _onlinecounter > 0 } /** * Check if Barix device is idle (not playing) * @return true if idle */ fun isIdle() : Boolean{ return statusData == 0 } /** * Check if Barix device is playing * @return true if playing */ fun isPlaying() : Boolean{ return statusData == 1 } /** * Send data to Barix device via UDP * @param data The data to send */ fun SendData(data: ByteArray, cbOK: Consumer, cbFail: Consumer) { if (data.isNotEmpty()) { CoroutineScope(Dispatchers.IO).launch { val bb = ByteBuffer.wrap(data) while(bb.hasRemaining()){ try { val chunk = ByteArray(if (bb.remaining() > maxUDPsize) maxUDPsize else bb.remaining()) bb.get(chunk) println("Buffer remain: $bufferRemain, sending chunk size: ${chunk.size}") while(bufferRemain){ val command = StringBuilder("RELAY;") var binary = 0 relays.forEach { if (it in 1..8) { binary = binary or (1 shl (it - 1)) } } command.append(binary.toString()).append("@") SendCommand(command.toString()) } /** * Deactivate relay on Barix device */ fun DeactivateRelay(){ SendCommand("RELAY;0@") } /** * Send command to Barix device * @param command The command to send * @return true if successful */ fun SendCommand(command: String): Boolean { try { if (_tcp!=null){ if (!_tcp!!.isClosed){ val bb = command.toByteArray() val size = bb.size + 4 val b4 = byteArrayOf( (size shr 24 and 0xFF).toByte(), (size shr 16 and 0xFF).toByte(), (size shr 8 and 0xFF).toByte(), (size and 0xFF).toByte() ) val out = _tcp!!.getOutputStream() out.write(b4) out.write(bb) out.flush() Logger.info { "SendCommand to $ipaddress : $command" } return true }else { Logger.error { "Socket to $ipaddress is not connected" } } } else { Logger.error { "Socket to $ipaddress is null" } } } catch (e: Exception) { Logger.error { "Failed to SendCommand to $ipaddress, Message : ${e.message}" } } return false } }