commit 08/10/2025

BarixConnection Activate Deactivate Relays
This commit is contained in:
2025-10-08 16:33:19 +07:00
parent efe243e440
commit 2ad26c3ef6
4 changed files with 215 additions and 5 deletions

View File

@@ -160,16 +160,20 @@ fun main() {
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 _tcp = barixserver.getSocket(cmd.ipaddress)
val _streamer = StreamerOutputs[cmd.ipaddress] val _streamer = StreamerOutputs[cmd.ipaddress]
val _sc = db.soundchannelDB.List.find { it.ip == cmd.ipaddress } val _sc = db.soundchannelDB.List.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
_bc.commandsocket = _tcp
StreamerOutputs[cmd.ipaddress] = _bc StreamerOutputs[cmd.ipaddress] = _bc
Logger.info { "Created new Streamer Output for channel ${_sc.channel} with IP ${cmd.ipaddress}" } Logger.info { "Created new Streamer Output for channel ${_sc.channel} with IP ${cmd.ipaddress}" }
} else Logger.warn { "soundChannelDB doesn't have soundchannel with IP ${cmd.ipaddress}" } } else Logger.warn { "soundChannelDB doesn't have soundchannel with IP ${cmd.ipaddress}" }
@@ -182,6 +186,21 @@ fun main() {
_streamer.vu = cmd.vu _streamer.vu = cmd.vu
_streamer.bufferRemain = cmd.buffremain _streamer.bufferRemain = cmd.buffremain
_streamer.statusData = cmd.statusdata _streamer.statusData = cmd.statusdata
// cek apakah koneksi TCP nya ganti
if (_streamer.commandsocket == null) {
_streamer.commandsocket = _tcp
} else {
if (_streamer.commandsocket != _tcp) {
// ganti koneksi
try {
_streamer.commandsocket?.close()
} catch (ex: Exception) {
Logger.error(ex) { "Error closing previous TCP command socket for ${cmd.ipaddress}" }
}
_streamer.commandsocket = _tcp
}
}
} }
} }

View File

@@ -1,4 +1,5 @@
import audio.AudioFileInfo import audio.AudioFileInfo
import barix.BarixConnection
import codes.Result_GetSoundbankFiles import codes.Result_GetSoundbankFiles
import codes.Somecodes.Companion.Get_ANN_ID import codes.Somecodes.Companion.Get_ANN_ID
import codes.Somecodes.Companion.IsAlphabethic import codes.Somecodes.Companion.IsAlphabethic
@@ -89,6 +90,25 @@ class MainExtension01 {
return false return false
} }
/**
* Find BarixConnection by BroadcastZones description
* @param zonename BroadcastZones description
* @return BarixConnection if found, null if not found or invalid
*/
fun Get_Barix_Connection_by_ZoneName(zonename: String) : BarixConnection? {
if (ValidString(zonename)){
val bz = db.broadcastDB.List.find{ it.description == zonename }
val sc = if (bz!=null) db.soundchannelDB.List.find { it.channel == bz.SoundChannel } else null
val ip = sc?.ip ?: ""
if (ValidIPV4(ip)){
// ketemu ip-nya
return StreamerOutputs[ip]
}
}
return null
}
/** /**
* find SoundChannel IP from BroadcastZones description * find SoundChannel IP from BroadcastZones description
* @param bz List of BroadcastZones description * @param bz List of BroadcastZones description
@@ -550,8 +570,18 @@ class MainExtension01 {
if (AllStreamerOutputIdle(ips)){ if (AllStreamerOutputIdle(ips)){
val afi = audioPlayer.LoadAudioFile(qp.Message) val afi = audioPlayer.LoadAudioFile(qp.Message)
if (afi.isValid()){ if (afi.isValid()){
// file bisa di load, kirim ke masing masing Streamer Output by IP address // file bisa di load, kirim ke masing-masing Streamer Output by IP address
ips.forEach { ip -> StreamerOutputs[ip]?.SendData(afi.bytes, { db.Add_Log("AAS", it) }, { db.Add_Log("AAS", it) }) } Activate_Relays(zz)
ips.forEach { ip ->
// send byte array to streamer output
StreamerOutputs[ip]?.SendData(afi.bytes,
{
Deactivate_Relays(zz)
db.Add_Log("AAS", it) },
{
Deactivate_Relays(zz)
db.Add_Log("AAS", it) })
}
val logmessage = val logmessage =
"Broadcast started PAGING with Filename '${qp.Message}' to zones: ${qp.BroadcastZones}" "Broadcast started PAGING with Filename '${qp.Message}' to zones: ${qp.BroadcastZones}"
@@ -640,7 +670,18 @@ class MainExtension01 {
// file siap broadcast // file siap broadcast
val targetafi = audioPlayer.LoadAudioFile(targetfile) val targetafi = audioPlayer.LoadAudioFile(targetfile)
if (targetafi.isValid()) { if (targetafi.isValid()) {
ips.forEach { ip -> StreamerOutputs[ip]?.SendData(targetafi.bytes, { db.Add_Log("AAS", it) }, {db.Add_Log("AAS", it) }) } // activate relays from broadcast zone
Activate_Relays(zz)
ips.forEach { ip ->
// send byte array to streamer output
StreamerOutputs[ip]?.SendData(targetafi.bytes,
{
Deactivate_Relays(zz)
db.Add_Log("AAS", it) },
{
Deactivate_Relays(zz)
db.Add_Log("AAS", it) })
}
val logmsg = val logmsg =
"Broadcast started SHALAT message with generated file '$targetfile' to zones: ${qp.BroadcastZones}" "Broadcast started SHALAT message with generated file '$targetfile' to zones: ${qp.BroadcastZones}"
@@ -730,7 +771,18 @@ class MainExtension01 {
// file siap broadcast // file siap broadcast
val targetafi = audioPlayer.LoadAudioFile(targetfile) val targetafi = audioPlayer.LoadAudioFile(targetfile)
if (targetafi.isValid()) { if (targetafi.isValid()) {
ips.forEach { ip -> StreamerOutputs[ip]?.SendData(targetafi.bytes, { db.Add_Log("AAS", it) }, { db.Add_Log("AAS", it) }) } // activate relays from broadcast zone
Activate_Relays(zz)
ips.forEach { ip ->
// send byte array to streamer output
StreamerOutputs[ip]?.SendData(targetafi.bytes,
{
Deactivate_Relays(zz)
db.Add_Log("AAS", it) },
{
Deactivate_Relays(zz)
db.Add_Log("AAS", it) })
}
val logmsg = val logmsg =
"Broadcast started TIMER message with generated file '$targetfile' to zones: ${qa.BroadcastZones}" "Broadcast started TIMER message with generated file '$targetfile' to zones: ${qa.BroadcastZones}"
@@ -779,6 +831,37 @@ class MainExtension01 {
return false return false
} }
fun Activate_Relays(zz: List<String>){
zz.forEach { zonename ->
val bz = db.broadcastDB.List.find { it.description == zonename }
if (bz!=null){
val bc = Get_Barix_Connection_by_ZoneName(zonename)
if (bc!=null){
// ada barix connection
val relays = bz.bp.split(",")
.map { it.trim()}
.filter { it.isNotBlank() }
.filter { IsNumber(it) && it.toInt() in 1..8 }
.map{ it.toInt() }
if (relays.isNotEmpty()) bc.ActivateRelay(relays)
}
}
}
}
fun Deactivate_Relays(zz: List<String>){
zz.forEach { zonename ->
val bz = db.broadcastDB.List.find { it.description == zonename }
if (bz!=null){
val bc = Get_Barix_Connection_by_ZoneName(zonename)
bc?.DeactivateRelay()
}
}
}
fun Read_Queue_Soundbank() : Boolean{ fun Read_Queue_Soundbank() : Boolean{
db.queuetableDB.Get() db.queuetableDB.Get()
val list = db.queuetableDB.List.filter { it.Type=="SOUNDBANK" } val list = db.queuetableDB.List.filter { it.Type=="SOUNDBANK" }
@@ -864,7 +947,20 @@ class MainExtension01 {
//println("Successfully wrote WAV file: $targetfile") //println("Successfully wrote WAV file: $targetfile")
val targetafi = audioPlayer.LoadAudioFile(targetfile) val targetafi = audioPlayer.LoadAudioFile(targetfile)
if (targetafi.isValid()) { if (targetafi.isValid()) {
ips.forEach { ip -> StreamerOutputs[ip]?.SendData(targetafi.bytes, { db.Add_Log("AAS", it) }, { db.Add_Log("AAS", it) }) } // activate relays from broadcast zone
Activate_Relays(zz)
ips.forEach { ip ->
// send byte array to streamer output
StreamerOutputs[ip]?.SendData(targetafi.bytes,
{
Deactivate_Relays(zz)
db.Add_Log("AAS", it)
}, {
Deactivate_Relays(zz)
db.Add_Log("AAS", it)
})
}
val logmsg = val logmsg =
"Broadcast started SOUNDBANK message with generated file '$targetfile' to zones: ${qa.BroadcastZones}" "Broadcast started SOUNDBANK message with generated file '$targetfile' to zones: ${qa.BroadcastZones}"

View File

@@ -6,9 +6,11 @@ import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay import kotlinx.coroutines.delay
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import org.tinylog.Logger
import java.net.DatagramPacket import java.net.DatagramPacket
import java.net.DatagramSocket import java.net.DatagramSocket
import java.net.InetSocketAddress import java.net.InetSocketAddress
import java.net.Socket
import java.nio.ByteBuffer import java.nio.ByteBuffer
import java.util.function.Consumer import java.util.function.Consumer
@@ -21,6 +23,7 @@ class BarixConnection(val index: UInt, var channel: String, val ipaddress: Strin
private val udp = DatagramSocket(0) private val udp = DatagramSocket(0)
private val inet = InetSocketAddress(ipaddress, port) private val inet = InetSocketAddress(ipaddress, port)
private val maxUDPsize = 1000 private val maxUDPsize = 1000
private var _tcp: Socket? = null
/** /**
@@ -53,6 +56,15 @@ class BarixConnection(val index: UInt, var channel: String, val ipaddress: Strin
_onlinecounter = 5 _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 * Decrement online counter, if counter reaches 0, the device is considered offline
*/ */
@@ -142,4 +154,76 @@ class BarixConnection(val index: UInt, var channel: String, val ipaddress: Strin
fun toJsonString(): String { fun toJsonString(): String {
return Somecodes.toJsonString(toJsonNode()) return Somecodes.toJsonString(toJsonNode())
} }
/**
* Activate relay on Barix device
* @param relays The relay numbers to activate (1-8)
* @return true if successful
*/
fun ActivateRelay(vararg relays: Int){
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())
}
fun ActivateRelay(relays: List<Int>){
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
}
} }

View File

@@ -102,4 +102,15 @@ class TCP_Barix_Command_Server {
} }
return false 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]
}
} }