commit 14/01/2026
This commit is contained in:
@@ -185,6 +185,14 @@ class Somecodes {
|
|||||||
return Path.of(path).fileName.toString()
|
return Path.of(path).fileName.toString()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun ToByteArray(vararg values: Int) : ByteArray {
|
||||||
|
val byteArray = ByteArray(values.size)
|
||||||
|
for (i in values.indices){
|
||||||
|
byteArray[i] = values[i].toByte()
|
||||||
|
}
|
||||||
|
return byteArray
|
||||||
|
}
|
||||||
|
|
||||||
fun ExtractFilesFromClassPath(resourcePath: String, outputDir: Path) {
|
fun ExtractFilesFromClassPath(resourcePath: String, outputDir: Path) {
|
||||||
try {
|
try {
|
||||||
val resource = Somecodes::class.java.getResource(resourcePath)
|
val resource = Somecodes::class.java.getResource(resourcePath)
|
||||||
|
|||||||
24
src/toa/SX2KBroadcastFromAI.kt
Normal file
24
src/toa/SX2KBroadcastFromAI.kt
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
package toa
|
||||||
|
|
||||||
|
@Suppress("unused")
|
||||||
|
data class SX2KBroadcastFromAI(val AIAddress: Int, val AIChannel: Int, val Zone: ByteArray = ByteArray(32)){
|
||||||
|
init {
|
||||||
|
require(AIAddress in 1..8 ) { "AIAddress must be in the range 1-8" }
|
||||||
|
require(AIChannel in 1..8) { "AIChannel must be in the range 8-8" }
|
||||||
|
}
|
||||||
|
fun ZoneSelect(AO: Int, ZoneNumber: Int, Broadcast: Boolean){
|
||||||
|
if (AO in 1..32 && ZoneNumber in 1..8){
|
||||||
|
val index = (AO - 1)
|
||||||
|
val bit = ZoneNumber - 1
|
||||||
|
if (Broadcast){
|
||||||
|
Zone[index] = (Zone[index].toInt() or (1 shl bit)).toByte()
|
||||||
|
} else {
|
||||||
|
Zone[index] = (Zone[index].toInt() and (1 shl bit).inv()).toByte()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun toString(): String {
|
||||||
|
return "SX2KBroadcastFromAI(AISlot=$AIAddress, AIChannel=$AIChannel)"
|
||||||
|
}
|
||||||
|
}
|
||||||
28
src/toa/SX2KCIN.kt
Normal file
28
src/toa/SX2KCIN.kt
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
package toa
|
||||||
|
|
||||||
|
data class SX2KCIN(val device: SX2KDevice, val address: Int, val Cin: Int, val state: Boolean) {
|
||||||
|
init{
|
||||||
|
when(device){
|
||||||
|
SX2KDevice.SX2000SM -> {
|
||||||
|
require(Cin in 1..8) { "Cin must be between 1 and 8 for SX2000SM" }
|
||||||
|
}
|
||||||
|
SX2KDevice.SX2000AO -> {
|
||||||
|
require(address in 1..32) { "Address must be between 1 and 32 for SX2000AO" }
|
||||||
|
require(Cin in 1..8) { "Cin must be between 1 and 8 for SX2000AO" }
|
||||||
|
}
|
||||||
|
SX2KDevice.SX2000AI -> {
|
||||||
|
require(address in 1..8) { "Address must be between 1 and 8 for SX2000AI" }
|
||||||
|
require(Cin in 1..16) { "Cin must be between 1 and 16 for SX2000AI" }
|
||||||
|
}
|
||||||
|
else -> throw IllegalArgumentException("Invalid device type")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
override fun toString(): String {
|
||||||
|
return when(device){
|
||||||
|
SX2KDevice.SX2000SM -> "SX2000SM - Cin: $Cin, State: $state"
|
||||||
|
SX2KDevice.SX2000AO -> "SX2000AO - Address: $address, Cin: $Cin, State: $state"
|
||||||
|
SX2KDevice.SX2000AI -> "SX2000AI - Address: $address, Cin: $Cin, State: $state"
|
||||||
|
else -> "Unknown Device"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
10
src/toa/SX2KDevice.kt
Normal file
10
src/toa/SX2KDevice.kt
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
package toa
|
||||||
|
|
||||||
|
@Suppress("unused")
|
||||||
|
enum class SX2KDevice(description: String) {
|
||||||
|
SX2000SM("SX2000SM"),
|
||||||
|
SX2000AI("SX2000AI"),
|
||||||
|
SX2000AO("SX2000AO"),
|
||||||
|
SX2000CI("SX2000CI"),
|
||||||
|
SX2000CO("SX2000CO")
|
||||||
|
}
|
||||||
159
src/toa/Sx2K.kt
Normal file
159
src/toa/Sx2K.kt
Normal file
@@ -0,0 +1,159 @@
|
|||||||
|
package toa
|
||||||
|
|
||||||
|
import codes.Somecodes.Companion.ToByteArray
|
||||||
|
import org.tinylog.Logger
|
||||||
|
import java.net.InetSocketAddress
|
||||||
|
import java.net.Socket
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by a Sx2K device.
|
||||||
|
* @param ipAddress The IP address of the Sx2K device. Default is 192.168.14.1
|
||||||
|
*/
|
||||||
|
@Suppress("unused")
|
||||||
|
class Sx2K(val ipAddress: String = "192.168.14.1") {
|
||||||
|
private var remotesocket : InetSocketAddress? = null
|
||||||
|
private val timeout = 2000
|
||||||
|
init {
|
||||||
|
try{
|
||||||
|
val inet = InetSocketAddress(ipAddress, 2005)
|
||||||
|
// connect trial
|
||||||
|
val socket = Socket()
|
||||||
|
socket.soTimeout = 2000
|
||||||
|
socket.connect(inet, 2000)
|
||||||
|
socket.close()
|
||||||
|
remotesocket = inet
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Logger.error { "Invalid IP address: $ipAddress , exception : ${e.message}" }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Start a BroadcastFromAI on the Sx2K device.
|
||||||
|
* @param Broadcast Vararg of SX2KBroadcastFromAI objects to start the broadcast
|
||||||
|
*/
|
||||||
|
fun StartBroadcastFromAI(vararg Broadcast: SX2KBroadcastFromAI){
|
||||||
|
if (remotesocket == null) {
|
||||||
|
Logger.error { "Cannot create BroadcastFromAI, invalid Sx2K device IP address: $ipAddress" }
|
||||||
|
return
|
||||||
|
}
|
||||||
|
try{
|
||||||
|
Socket().use { socket ->
|
||||||
|
socket.connect(remotesocket, timeout)
|
||||||
|
socket.soTimeout = timeout
|
||||||
|
val outputStream = socket.getOutputStream()
|
||||||
|
val inputStream = socket.getInputStream()
|
||||||
|
Broadcast.forEach { bc ->
|
||||||
|
val cmd : ByteArray = ToByteArray(0xA0, 0xAD, bc.AIAddress, bc.AIChannel) + bc.Zone
|
||||||
|
outputStream.write(cmd)
|
||||||
|
outputStream.flush()
|
||||||
|
val reply = ByteArray(2)
|
||||||
|
inputStream.read(reply)
|
||||||
|
if (reply[0]==0.toByte() && reply[1]==1.toByte()){
|
||||||
|
// DONE TRUE
|
||||||
|
Logger.info { "BroadcastFromAI succeeded for $bc" }
|
||||||
|
} else {
|
||||||
|
Logger.error { "BroadcastFromAI failed for $bc" }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Logger.error { "BroadcastFromAI failed , exception : ${e.message}" }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stop a BroadcastFromAI on the Sx2K device.
|
||||||
|
* @param Broadcast Vararg of SX2KBroadcastFromAI objects to stop the broadcast
|
||||||
|
*/
|
||||||
|
fun StopBroadcastFromAI(vararg Broadcast: SX2KBroadcastFromAI){
|
||||||
|
if (remotesocket == null) {
|
||||||
|
Logger.error { "Cannot create StopBroadcastFromAI, invalid Sx2K device IP address: $ipAddress" }
|
||||||
|
return
|
||||||
|
}
|
||||||
|
try{
|
||||||
|
Socket().use { socket ->
|
||||||
|
socket.connect(remotesocket, timeout)
|
||||||
|
socket.soTimeout = timeout
|
||||||
|
val outputStream = socket.getOutputStream()
|
||||||
|
val inputStream = socket.getInputStream()
|
||||||
|
Broadcast.forEach { bc ->
|
||||||
|
val cmd = ToByteArray(0xA1, 0xAD, bc.AIAddress, bc.AIChannel)
|
||||||
|
outputStream.write(cmd)
|
||||||
|
outputStream.flush()
|
||||||
|
val reply = ByteArray(2)
|
||||||
|
inputStream.read(reply)
|
||||||
|
if (reply[0]==0.toByte() && reply[1]==1.toByte()){
|
||||||
|
// DONE TRUE
|
||||||
|
Logger.info { "StopBroadcastFromAI succeeded for $bc" }
|
||||||
|
} else {
|
||||||
|
Logger.error { "StopBroadcastFromAI failed for $bc" }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Logger.error { "StopBroadcastFromAI failed , exception : ${e.message}" }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the state of virtual contact inputs on the Sx2K device.
|
||||||
|
* @param cin Vararg of SX2KCIN objects to set the state
|
||||||
|
*/
|
||||||
|
fun VirtualContactInput(vararg cin : SX2KCIN){
|
||||||
|
if (remotesocket == null) {
|
||||||
|
Logger.error { "Cannot create VirtualContactInput, invalid Sx2K device IP address: $ipAddress" }
|
||||||
|
return
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
Socket().use { socket ->
|
||||||
|
socket.connect(remotesocket, timeout)
|
||||||
|
socket.soTimeout = timeout
|
||||||
|
val outputStream = socket.getOutputStream()
|
||||||
|
val inputStream = socket.getInputStream()
|
||||||
|
cin.forEach { cc ->
|
||||||
|
val cmd : ByteArray = when(cc.device){
|
||||||
|
SX2KDevice.SX2000SM -> {
|
||||||
|
if (cc.Cin in 1..8){
|
||||||
|
ToByteArray(0xA0, 0xA0, cc.Cin, if (cc.state) 0x01 else 0x00)
|
||||||
|
} else ByteArray(0)
|
||||||
|
}
|
||||||
|
SX2KDevice.SX2000AO -> {
|
||||||
|
if (cc.address in 1..32){
|
||||||
|
if (cc.Cin in 1..8){
|
||||||
|
ToByteArray(0xA0, 0xA1, cc.address, cc.Cin, if (cc.state) 0x01 else 0x00)
|
||||||
|
} else ByteArray(0)
|
||||||
|
} else ByteArray(0)
|
||||||
|
}
|
||||||
|
SX2KDevice.SX2000AI -> {
|
||||||
|
if (cc.address in 1..8){
|
||||||
|
if (cc.Cin in 1..16){
|
||||||
|
ToByteArray(0xA0, 0xA2, cc.address, cc.Cin, if (cc.state) 0x01 else 0x00)
|
||||||
|
} else ByteArray(0)
|
||||||
|
} else ByteArray(0)
|
||||||
|
}
|
||||||
|
else -> ByteArray(0)
|
||||||
|
}
|
||||||
|
if (cmd.isNotEmpty()){
|
||||||
|
outputStream.write(cmd)
|
||||||
|
outputStream.flush()
|
||||||
|
val reply = ByteArray(2)
|
||||||
|
inputStream.read(reply)
|
||||||
|
if (reply[0]==0.toByte() && reply[1]==1.toByte()){
|
||||||
|
// DONE TRUE
|
||||||
|
Logger.info { "VirtualContactInput succeeded for $cc" }
|
||||||
|
} else {
|
||||||
|
Logger.error { "VirtualContactInput failed for $cc" }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} catch (e : Exception){
|
||||||
|
Logger.error { "VirtualContactInput failed , exception : ${e.message}" }
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -4,7 +4,6 @@ import codes.Somecodes
|
|||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import org.tinylog.Logger
|
|
||||||
import java.net.Inet4Address
|
import java.net.Inet4Address
|
||||||
import java.net.InetSocketAddress
|
import java.net.InetSocketAddress
|
||||||
import java.net.Socket
|
import java.net.Socket
|
||||||
@@ -17,6 +16,7 @@ import java.util.function.BiConsumer
|
|||||||
* @param ipaddress IP address of the VX3K device, default to 192.168.14.1
|
* @param ipaddress IP address of the VX3K device, default to 192.168.14.1
|
||||||
* @param port Port number of the VX3K device, from 50050-50053 default to 50053
|
* @param port Port number of the VX3K device, from 50050-50053 default to 50053
|
||||||
*/
|
*/
|
||||||
|
@Suppress("unused")
|
||||||
class Vx3K(val ipaddress : String = "192.168.14.1", val port : Int = 50053) {
|
class Vx3K(val ipaddress : String = "192.168.14.1", val port : Int = 50053) {
|
||||||
private val remotesocket : InetSocketAddress
|
private val remotesocket : InetSocketAddress
|
||||||
init{
|
init{
|
||||||
@@ -31,21 +31,6 @@ class Vx3K(val ipaddress : String = "192.168.14.1", val port : Int = 50053) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Connect to the VX3K device
|
|
||||||
* @param timeout Connection timeout in milliseconds, default to 30000 ms
|
|
||||||
*/
|
|
||||||
fun Connect(timeout: Int = 30000){
|
|
||||||
try{
|
|
||||||
val socket = Socket()
|
|
||||||
// read timeout 5 seconds
|
|
||||||
socket.soTimeout = 5000
|
|
||||||
socket.connect(remotesocket, timeout)
|
|
||||||
} catch (e : Exception){
|
|
||||||
Logger.error { "Failed to connect with ${remotesocket.hostName}:${remotesocket.port}, Message: ${e.message}" }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Virtual Contact Input (Commmand 0x1001)
|
* Virtual Contact Input (Commmand 0x1001)
|
||||||
* @param ID : Device ID for VX3K, range 0 - 31
|
* @param ID : Device ID for VX3K, range 0 - 31
|
||||||
@@ -226,7 +211,7 @@ class Vx3K(val ipaddress : String = "192.168.14.1", val port : Int = 50053) {
|
|||||||
try{
|
try{
|
||||||
val tcp = Socket()
|
val tcp = Socket()
|
||||||
tcp.soTimeout = 5000
|
tcp.soTimeout = 5000
|
||||||
tcp.connect(remotesocket, 30000)
|
tcp.connect(remotesocket, 5000)
|
||||||
val outstream = tcp.getOutputStream()
|
val outstream = tcp.getOutputStream()
|
||||||
val instream = tcp.getInputStream()
|
val instream = tcp.getInputStream()
|
||||||
outstream.write(command)
|
outstream.write(command)
|
||||||
|
|||||||
Reference in New Issue
Block a user