-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 9feabe9
Showing
121 changed files
with
114,985 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
.idea/ | ||
**/target/ | ||
lsp/ | ||
*.log | ||
*.iml |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
= Klanglicht 3 - Kotlin | ||
:doctype: book | ||
:description: Documentation for the klanglicht project. | ||
:keywords: kotlin, dmx, serial-usb | ||
:icons: font | ||
:toc: | ||
:toc-title: Inhalt | ||
:toclevels: 10 | ||
|
||
== History and current state of the project (April 2023) | ||
|
||
=== History | ||
|
||
This project started as a simple proof of concept if it would be possible to get some simple RGB light working | ||
using a DMX interface. | ||
|
||
After researching about possible interfaces I decided for the Eurolite DMX Pro 512 for which I was able to find some information about it's link:/resources/hardware/Eurolite_USB-DMX512-PRO_serial-protocol_discussion-thread.pdf[serial protocol]. | ||
|
||
Another challenge was to find a reliable serial port library which is also available on other platforms as Windows which I use to develop the software. Here I decided for the fazecast jSerialComm library which also is playing well on the raspberry pi mini computers (which was mandatory as I wanted to set up a little raspy applicance lighting in the living room). | ||
|
||
After playing around a bit a first prototype was implemented which was able to fade in a color from black and vice versa (wow!). | ||
|
||
In the meantime (and about four years later) the project went through different stages ranging from kind of modular approach to pure chaos messing up UI code with logic. | ||
In between the UI was also capable of reading and playing time code. But this turned out | ||
not to be reliable enough to use it in production environments so I tossed it. | ||
|
||
The current flavor of the project which you have in front of you now has a layered approach which strictly separates the technical stuff needed to talk with the DMX interface from the client code. The interface to the outside world such as a JAva-FX UI which still exists and a web interface which is not fully implemented yet is the REST module. | ||
With this approach it is possible to run the server component in form a little shaded jar on a mini computer such as the raspberry pi while running a complex user interface elsewhere. | ||
|
||
This is a complete rewrite in kotlin as I no longer want to write java code. | ||
To make my life easier a bit and because I only have access to one DMX interface which I anaged to find documentation for, I have | ||
boiled down everything to be dedicated to this which is the Eurolite DMX 512 Pro. | ||
|
||
A printout of the thread with those golden informations which kick started me once back and the original hardware manual are attached to this project | ||
|
||
* link:docs/hardware/eurolite/Eurolite_USB-DMX512-PRO_serial-protocol_discussion-thread.pdf[Discussion Thread (German)] | ||
* link:docs/hardware/eurolite/Eurolite_USB-DMX512_PRO_manual_german.pdf[Manual (German)] | ||
|
||
== Current State | ||
|
||
As I just started to convert the project to kotlin (the original Java code will remain private as ther is a lot of chaos...) | ||
the REST interface itself is not yet implemented (also because I do not know which framework I want to use. | ||
Spring boot seems not to be appropriate anymore along with kotlin and Micronaut seems to be abandonded and my | ||
current experience with the latter during my professional work life is not so good. | ||
|
Binary file added
BIN
+95.6 KB
docs/hardware/eurolite/Eurolite_USB-DMX512-PRO_serial-protocol_discussion-thread.pdf
Binary file not shown.
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||
xmlns="http://maven.apache.org/POM/4.0.0" | ||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> | ||
<modelVersion>4.0.0</modelVersion> | ||
<packaging>jar</packaging> | ||
|
||
<parent> | ||
<groupId>de.visualdigits.kotlin</groupId> | ||
<artifactId>klanglicht-kt</artifactId> | ||
<version>${revision}</version> | ||
<relativePath>../pom.xml</relativePath> | ||
</parent> | ||
|
||
<artifactId>klanglicht-core</artifactId> | ||
<version>${revision}</version> | ||
|
||
<dependencies> | ||
|
||
<!-- common stuff --> | ||
<dependency> | ||
<groupId>org.apache.commons</groupId> | ||
<artifactId>commons-lang3</artifactId> | ||
<version>3.12.0</version> | ||
</dependency> | ||
<dependency> | ||
<groupId>commons-codec</groupId> | ||
<artifactId>commons-codec</artifactId> | ||
<version>1.15</version> | ||
</dependency> | ||
<dependency> | ||
<groupId>com.google.guava</groupId> | ||
<artifactId>guava</artifactId> | ||
<version>31.1-jre</version> | ||
</dependency> | ||
|
||
<!-- jackson --> | ||
<dependency> | ||
<groupId>com.fasterxml.jackson.core</groupId> | ||
<artifactId>jackson-core</artifactId> | ||
<version>${version.jackson}</version> | ||
</dependency> | ||
<dependency> | ||
<groupId>com.fasterxml.jackson.core</groupId> | ||
<artifactId>jackson-annotations</artifactId> | ||
<version>${version.jackson}</version> | ||
</dependency> | ||
<dependency> | ||
<groupId>com.fasterxml.jackson.core</groupId> | ||
<artifactId>jackson-databind</artifactId> | ||
<version>${version.jackson}</version> | ||
</dependency> | ||
<dependency> | ||
<groupId>com.fasterxml.jackson.dataformat</groupId> | ||
<artifactId>jackson-dataformat-xml</artifactId> | ||
<version>${version.jackson}</version> | ||
</dependency> | ||
<dependency> | ||
<groupId>com.fasterxml.jackson.module</groupId> | ||
<artifactId>jackson-module-kotlin</artifactId> | ||
<version>${version.jackson}</version> | ||
</dependency> | ||
<dependency> | ||
<groupId>com.fasterxml.jackson.datatype</groupId> | ||
<artifactId>jackson-datatype-jsr310</artifactId> | ||
<version>${version.jackson}</version> | ||
</dependency> | ||
|
||
<!-- serial port --> | ||
<dependency> | ||
<groupId>io.github.java-native</groupId> | ||
<artifactId>jssc</artifactId> | ||
<version>2.9.4</version> | ||
</dependency> | ||
</dependencies> | ||
</project> |
59 changes: 59 additions & 0 deletions
59
...glicht-core/src/main/kotlin/de/visualdigits/kotlin/klanglicht/dmx/AbstractDMXInterface.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
package de.visualdigits.kotlin.klanglicht.dmx | ||
|
||
import org.apache.commons.lang3.StringUtils | ||
|
||
|
||
abstract class AbstractDMXInterface : DMXInterface { | ||
|
||
protected val dmxFrame: DmxFrame = DmxFrame() | ||
|
||
override fun toString(): String { | ||
return dmxFrame.dump() | ||
} | ||
|
||
override fun repr(): String { | ||
val lst = ArrayList<String>() | ||
for (b in dmxFrame.frame()) { | ||
lst.add(StringUtils.leftPad(Integer.toHexString(b.toInt()), 8, '0')) | ||
} | ||
return lst.toString() | ||
} | ||
|
||
override fun open(portName: String) {} | ||
|
||
override fun close() {} | ||
|
||
override fun read(): ByteArray { | ||
return dmxFrame.data | ||
} | ||
|
||
override fun write(dmxFrame: DmxFrame) {} | ||
|
||
override fun setChannel(channel: Int, value: Int) { | ||
dmxFrame.set(channel, value) | ||
} | ||
|
||
override fun setData(baseChannel: Int, data: ByteArray) { | ||
dmxFrame.set(baseChannel, data) | ||
} | ||
|
||
override fun clearChannels() { | ||
for (i in 1..511) { | ||
setChannel(i, 0) | ||
} | ||
} | ||
|
||
override fun getChannel(channel: Int): Int { | ||
return dmxFrame.get(4 + channel) | ||
} | ||
|
||
override fun clear() { | ||
initFrame() | ||
write() | ||
} | ||
|
||
override fun initFrame() { | ||
dmxFrame.init() | ||
} | ||
} | ||
|
104 changes: 104 additions & 0 deletions
104
klanglicht-core/src/main/kotlin/de/visualdigits/kotlin/klanglicht/dmx/DMXInterface.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,104 @@ | ||
package de.visualdigits.kotlin.klanglicht.dmx | ||
|
||
|
||
interface DMXInterface { | ||
|
||
/** | ||
* Opens the given serial port for communication with the physical device. | ||
* | ||
* @param portName The port name (i.e. 'COM9'. | ||
*/ | ||
fun open(portName: String) | ||
|
||
/** | ||
* Closes the current serial port. | ||
*/ | ||
fun close() | ||
|
||
/** | ||
* Writes the current internal data bytes to the device. | ||
*/ | ||
fun write() | ||
|
||
/** | ||
* Writes the given data bytes to the device. | ||
* | ||
* @param data The frame data to write. | ||
*/ | ||
fun write(data: ByteArray) | ||
|
||
/** | ||
* Writes the given data bytes to the device. | ||
* | ||
* @param dmxFrame The frame data to write. | ||
*/ | ||
fun write(dmxFrame: DmxFrame) | ||
|
||
/** | ||
* Returns the current frame data. | ||
*/ | ||
fun read(): ByteArray? | ||
|
||
/** | ||
* Clears all 512 DMX channels in the internal data bytes by setting to 0. | ||
*/ | ||
fun clearChannels() | ||
|
||
/** | ||
* 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) | ||
|
||
/** | ||
* 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) | ||
|
||
/** | ||
* 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 | ||
|
||
/** | ||
* Initializes a new DMX frame appropriate for the target device. | ||
*/ | ||
fun initFrame() | ||
|
||
/** | ||
* Sets all channels to 0. | ||
*/ | ||
fun clear() | ||
|
||
fun repr(): String? | ||
|
||
fun isOpen(): Boolean | ||
|
||
companion object { | ||
|
||
private var dmxInterface: DMXInterface? = null | ||
|
||
fun instance(): DMXInterface = dmxInterface!! | ||
|
||
fun load(type: DMXInterfaceType): DMXInterface { | ||
if (dmxInterface == null) { | ||
dmxInterface = when (type) { | ||
DMXInterfaceType.Eurolite512Pro -> DMXInterfaceEurolite512Pro() | ||
DMXInterfaceType.Dummy -> DMXInterfaceDummy() | ||
DMXInterfaceType.Rest -> DMXInterfaceRest() | ||
} | ||
} | ||
return dmxInterface!! | ||
} | ||
} | ||
} |
30 changes: 30 additions & 0 deletions
30
klanglicht-core/src/main/kotlin/de/visualdigits/kotlin/klanglicht/dmx/DMXInterfaceDummy.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
package de.visualdigits.kotlin.klanglicht.dmx | ||
|
||
|
||
class DMXInterfaceDummy() : AbstractDMXInterface() { | ||
|
||
override fun toString(): String { | ||
return repr() | ||
} | ||
|
||
override fun open(portName: String) { | ||
println("### open") | ||
} | ||
|
||
override fun close() { | ||
println("### close") | ||
} | ||
|
||
override fun write() { | ||
println(toString()) | ||
} | ||
|
||
override fun read(): ByteArray { | ||
return ByteArray(0) | ||
} | ||
|
||
override fun write(data: ByteArray) {} | ||
|
||
override fun isOpen(): Boolean = true | ||
} | ||
|
58 changes: 58 additions & 0 deletions
58
...-core/src/main/kotlin/de/visualdigits/kotlin/klanglicht/dmx/DMXInterfaceEurolite512Pro.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
package de.visualdigits.kotlin.klanglicht.dmx | ||
|
||
import jssc.SerialPort | ||
import jssc.SerialPortException | ||
import org.apache.commons.lang3.StringUtils | ||
|
||
class DMXInterfaceEurolite512Pro : AbstractDMXInterface() { | ||
|
||
private var serialPort: SerialPort? = null | ||
|
||
override fun open(portName: String) { | ||
serialPort = null | ||
if (!StringUtils.isEmpty(portName)) { | ||
try { | ||
serialPort = SerialPort(portName) | ||
serialPort?.openPort() | ||
serialPort?.setParams(9600, 8, 1, 0) | ||
} catch (e: Exception) { | ||
System.err.println("Could not open DMX port '$portName'") | ||
} | ||
} | ||
} | ||
|
||
override fun close() { | ||
if (isOpen()) { | ||
try { | ||
serialPort?.closePort() | ||
} catch (e: SerialPortException) { | ||
throw IllegalStateException("Could not close port", e) | ||
} | ||
} | ||
} | ||
|
||
override fun write() { | ||
write(dmxFrame) | ||
} | ||
|
||
override fun write(data: ByteArray) { | ||
write(DmxFrame(data)) | ||
} | ||
|
||
override fun write(dmxFrame: DmxFrame) { | ||
if (isOpen()) { | ||
try { | ||
val frame = dmxFrame.frame() | ||
serialPort?.writeBytes(frame) | ||
} catch (e: SerialPortException) { | ||
throw IllegalStateException("Could write dmxFrame to port", e) | ||
} | ||
} else { | ||
throw IllegalStateException("Tried to write to non open port") | ||
} | ||
} | ||
|
||
override fun isOpen(): Boolean { | ||
return serialPort != null && serialPort?.isOpened == true | ||
} | ||
} |
Oops, something went wrong.