Skip to content

Commit

Permalink
Work on handlers and controllers (wip)
Browse files Browse the repository at this point in the history
  • Loading branch information
sknull committed Dec 28, 2023
1 parent 2ca7a62 commit 59162a7
Show file tree
Hide file tree
Showing 77 changed files with 1,044 additions and 942 deletions.
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
package de.visualdigits.kotlin.klanglicht.model.color

import de.visualdigits.kotlin.klanglicht.model.parameter.Parameter
import java.lang.IllegalArgumentException
import kotlin.math.min
import kotlin.math.roundToInt

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,10 @@ class DmxFrame(
return "DmxFrame [${dump()}]"
}

fun frame(): ByteArray = Bytes.concat(header, data, footer)
/**
* Returns the bytes for a complete frame including header and footer.
*/
fun getFrameBytes(): ByteArray = Bytes.concat(header, data, footer)

/**
* Sets all data bytes to 0.
Expand All @@ -48,14 +51,6 @@ class DmxFrame(
return data[channel - 1].toInt() and BYTE_MASK
}

fun set(channel: Int, value: Int): Int {
val oldValue = data[channel - 1].toInt() and BYTE_MASK
if (value != oldValue) {
data[channel - 1] = value.toByte()
}
return oldValue
}

fun set(baseChannel: Int, bytes: ByteArray) {
bytes.copyInto(data, baseChannel - 1)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ open class DmxInterface {

fun repr(): String {
val lst = ArrayList<String>()
for (b in dmxFrame.frame()) {
for (b in dmxFrame.getFrameBytes()) {
lst.add(StringUtils.leftPad(Integer.toHexString(b.toInt()), 8, '0'))
}
return lst.toString()
Expand Down Expand Up @@ -93,7 +93,7 @@ open class DmxInterface {
open fun write() {
if (isOpen()) {
try {
serialPort?.writeBytes(dmxFrame.frame())
serialPort?.writeBytes(dmxFrame.getFrameBytes())
} catch (e: SerialPortException) {
throw IllegalStateException("Could write dmxFrame to port", e)
}
Expand All @@ -102,38 +102,6 @@ open class DmxInterface {
}
}

/**
* Sets the given DMX channel in the internal data bytes to the given value.
*
* @param channel The channel to set [1..512].
* @param value The value to set [0..255].
*/
fun setChannel(channel: Int, value: Int) {
dmxFrame.set(channel, value)
}

/**
* Sets the given DMX channel in the internal data bytes to the given value.
*
* @param baseChannel The base channel to set [1..512].
* @param data The bytes to set.
*/
fun setData(baseChannel: Int, data: ByteArray) {
dmxFrame.set(baseChannel, data)
}

/**
* Returns the currently set value of the given DMX channel.<br></br>
* This method does not actually read from the device but returns
* the current value form the internal data bytes.
*
* @param channel The DMX channel to retrieve [1..512].
* @return byte
*/
fun getChannel(channel: Int): Int {
return dmxFrame.get(channel) // todo had offset of 4 - why?
}

/**
* Sets all channels to 0.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,8 @@ package de.visualdigits.kotlin.klanglicht.model.dmx

import org.slf4j.LoggerFactory

class DmxRepeater(
val dmxInterface: DmxInterface,
val dmxFrameTime: Long
class DmxRepeater private constructor(
val dmxInterface: DmxInterface
) : Thread("DMX Repeater") {

private var log = LoggerFactory.getLogger(DmxRepeater::class.java)
Expand All @@ -19,10 +18,9 @@ class DmxRepeater(

fun instance(
dmxInterface: DmxInterface,
dmxFrameTime: Long = 200
): DmxRepeater {
if (dmxRepeater == null) {
dmxRepeater = DmxRepeater(dmxInterface, dmxFrameTime / 2)
dmxRepeater = DmxRepeater(dmxInterface)
dmxRepeater?.start()
}
return dmxRepeater!!
Expand All @@ -36,7 +34,7 @@ class DmxRepeater(
while (loop) {
if (running) {
dmxInterface.write()
sleep(dmxFrameTime)
sleep(1000)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package de.visualdigits.kotlin.klanglicht.model.hybrid


class HybridDevice(
val type: HybridDeviceType? = null,
val id: String = ""
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package de.visualdigits.kotlin.klanglicht.model.hybrid

enum class HybridDeviceType {
dmx,
shelly
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@ package de.visualdigits.kotlin.klanglicht.model.parameter
import com.fasterxml.jackson.module.kotlin.jacksonMapperBuilder
import de.visualdigits.kotlin.klanglicht.model.preferences.Preferences
import java.io.File
import java.lang.IllegalArgumentException

class Scene(
val name: String,
val parameterSet: List<ParameterSet>
) : Fadeable<Scene> {

companion object {
private val mapper = jacksonMapperBuilder().build()

Expand All @@ -17,6 +17,23 @@ class Scene(
}
}

/**
* Writes the given scene into the internal dmx frame of the interface.
*/
fun write(preferences: Preferences, write: Boolean = true) {
parameterSet
.sortedBy { it.baseChannel }
.forEach { parameterSet ->
val baseChannel = parameterSet.baseChannel
val bytes = (preferences.fixtures[baseChannel]?.map { channel ->
(parameterSet.parameterMap[channel.name] ?: 0).toByte()
} ?: listOf())
.toByteArray()
preferences.dmxInterface.dmxFrame.set(baseChannel, bytes)
if (write) preferences.dmxInterface.write()
}
}

override fun fade(
other: Any,
factor: Double
Expand All @@ -25,12 +42,14 @@ class Scene(
Scene(
name = "Frame $factor",
parameterSet = parameterSet
.zip(other.parameterSet)
.sortedBy { it.baseChannel }
.zip(other.parameterSet.sortedBy { it.baseChannel })
.map { (paramsFrom, paramsTo) ->
paramsFrom.fade(paramsTo, factor)
}
)
} else throw IllegalArgumentException("Cannot not fade another type")
}
else throw IllegalArgumentException("Cannot not fade another type")
}

fun fade(
Expand All @@ -43,10 +62,10 @@ class Scene(
var factor = 0.0

while (factor < 1.0) {
preferences.setScene(fade(other, factor))
fade(other, factor).write(preferences)
factor += step
Thread.sleep(dmxFrameTime)
}
preferences.setScene(other)
other.write(preferences)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ data class Dmx(
val port: String = "",
val interfaceType: DmxInterfaceType = DmxInterfaceType.Dummy,
val frameTime: Long = 40L,
val enableRepeater: Boolean = true,
val devices: List<DmxDevice> = listOf()
) {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,17 @@ import de.visualdigits.kotlin.klanglicht.model.dmx.DmxInterface
import de.visualdigits.kotlin.klanglicht.model.dmx.DmxInterfaceDummy
import de.visualdigits.kotlin.klanglicht.model.fixture.Channel
import de.visualdigits.kotlin.klanglicht.model.fixture.Fixtures
import de.visualdigits.kotlin.klanglicht.model.parameter.Scene
import de.visualdigits.kotlin.klanglicht.model.hybrid.HybridDevice
import java.io.File
import java.nio.file.Paths


@JsonIgnoreProperties("klanglichtDir", "dmxInterface", "fixtures", "serviceMap")
@JsonIgnoreProperties("klanglichtDir", "dmxInterface", "fixtures", "serviceMap", "stageMap")
data class Preferences(
val name: String = "",
val services: List<Service> = listOf(),
val shelly: Shelly = Shelly(),
val shelly: List<ShellyDevice> = listOf(),
val stage: List<HybridDevice> = listOf(),
val dmx: Dmx = Dmx()
) {

Expand All @@ -28,6 +29,8 @@ data class Preferences(

var serviceMap: Map<String, Service> = mapOf()

var stageMap: Map<String, HybridDevice> = mapOf()

fun init(klanglichtDir: File) {
this.klanglichtDir = klanglichtDir

Expand All @@ -40,9 +43,9 @@ data class Preferences(
}
}.toMap()

serviceMap = services.map { service ->
Pair(service.name, service)
}.toMap()
serviceMap = services.associateBy { it.name }

stageMap = stage.associateBy { it.id }

val dmxInterface = DmxInterface.load(dmx.interfaceType)
dmxInterface.open(dmx.port)
Expand Down Expand Up @@ -71,18 +74,4 @@ data class Preferences(
return preferences!!
}
}

/**
* Writes the given scene into the internal dmx frame of the interface.
*/
fun setScene(scene: Scene) {
scene.parameterSet.forEach { parameterSet ->
val baseChannel = parameterSet.baseChannel
val bytes = (fixtures[baseChannel]?.map { channel ->
(parameterSet.parameterMap[channel.name]?:0).toByte()
}?:listOf())
.toByteArray()
dmxInterface.dmxFrame.set(baseChannel, bytes)
}
}
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,5 @@ data class ShellyDevice(
val model: String = "",
val command: String = "",
val ipAddress: String = "",
val gain: Int = 0
val gain: Float = 0.0f
)
Original file line number Diff line number Diff line change
@@ -1,11 +1,8 @@
package de.visualdigits.kotlin.klanglicht.dmx

import de.visualdigits.kotlin.klanglicht.model.color.RGBColor
import de.visualdigits.kotlin.klanglicht.model.color.RGBWColor
import de.visualdigits.kotlin.klanglicht.model.dmx.DmxRepeater
import de.visualdigits.kotlin.klanglicht.model.parameter.IntParameter
import de.visualdigits.kotlin.klanglicht.model.parameter.ParameterSet
import de.visualdigits.kotlin.klanglicht.model.parameter.RotationParameter
import de.visualdigits.kotlin.klanglicht.model.parameter.Scene
import de.visualdigits.kotlin.klanglicht.model.preferences.Preferences
import org.junit.jupiter.api.Disabled
Expand All @@ -16,7 +13,7 @@ import kotlin.math.ceil
@Disabled("for local testing only")
class DmxInterfaceTest {

private val prefs = Preferences.load(
private val preferences = Preferences.load(
klanglichtDir = File(ClassLoader.getSystemResource(".klanglicht").toURI()),
preferencesFileName = System.getenv("preferencesFileName")?:"preferences_livingroom_dummy.json"
)
Expand All @@ -36,8 +33,8 @@ class DmxInterfaceTest {
)
)
)
prefs.setScene(scene)
prefs.dmxInterface.write()
scene.write(preferences)
preferences.dmxInterface.write()
}

@Test
Expand All @@ -55,8 +52,8 @@ class DmxInterfaceTest {
)
)
)
prefs.setScene(scene)
prefs.dmxInterface.write()
scene.write(preferences)
preferences.dmxInterface.write()
}

// @Test
Expand Down Expand Up @@ -147,7 +144,7 @@ class DmxInterfaceTest {
parameterSet1: ParameterSet,
parameterSet2: ParameterSet
) {
val dmxFrameTime = prefs.dmx.frameTime // millis
val dmxFrameTime = preferences.dmx.frameTime // millis
val steps = ceil(fadeDuration.toDouble() / dmxFrameTime.toDouble()).toInt()
val step = 1.0 / steps
for (f in 0..steps) {
Expand All @@ -159,7 +156,7 @@ class DmxInterfaceTest {
frame
)
)
prefs.setScene(scene)
scene.write(preferences)
Thread.sleep(dmxFrameTime)
}
}
Expand Down
Loading

0 comments on commit 59162a7

Please sign in to comment.