Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
.git
.github
node_modules
npm-debug.log*
coverage
.DS_Store
30 changes: 30 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
FROM node:24-alpine AS deps-server
WORKDIR /app
COPY package.json package-lock.json* ./
RUN npm ci --omit=dev

FROM node:24-alpine AS deps-test
WORKDIR /app
COPY package.json package-lock.json* ./
RUN npm ci

FROM node:24-alpine AS server
WORKDIR /app
ENV NODE_ENV=production
COPY --from=deps-server /app/node_modules ./node_modules
COPY --chown=node:node server.coffee ./
COPY --chown=node:node config.cson ./
COPY --chown=node:node lib ./lib
COPY --chown=node:node web ./web
USER node
EXPOSE 8080
EXPOSE 9910
EXPOSE 9909/udp
CMD ["node", "-r", "coffeescript/register", "server.coffee"]

FROM node:24-alpine AS test
WORKDIR /app
ENV NODE_ENV=test
COPY --from=deps-test /app/node_modules ./node_modules
COPY . .
CMD ["npm", "test"]
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ build:
npm rebuild

run-develop:
supervisor server.coffee
npm run dev

clean:
find node_modules -name .gitignore -exec rm -v {} \;
33 changes: 30 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,16 @@ UDP and WebSocket packet abstraction for multiple DMX controllers.

## Installing

First, get Node.js and npm. On Debian and related distros you most likely
want the `nodejs-legacy` and `npm` packages.
Use Node.js 24 LTS and npm.

With nvm:

nvm install 24
nvm use 24

Fetch the server's dependencies using npm.

npm install
npm ci

## Configuring

Expand All @@ -21,3 +25,26 @@ unconfigured.

npm start

## Development

npm run dev

## Client examples

Light client examples and run instructions are in [examples/README.md](examples/README.md).

## Docker

Build server image:

docker build --target server -t effectserver:server .

Run server container:

docker run --rm --read-only --security-opt no-new-privileges --cap-drop ALL -p 8080:8080 -p 9910:9910 -p 9909:9909/udp effectserver:server

Build and run test target:

docker build --target test -t effectserver:test .
docker run --rm effectserver:test

53 changes: 53 additions & 0 deletions examples/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# Examples

This folder contains example clients that communicate with `effectserver`.

## Prerequisites

From the project root:

npm ci
npm start

By default examples target:

- UDP host `127.0.0.1`
- UDP port `9909`
- WebSocket port `9910`

You can override UDP destination with environment variables:

export EFFECTSERVER_HOST=127.0.0.1
export EFFECTSERVER_UDP_PORT=9909

## CoffeeScript examples

Run from the project root with Node.js + CoffeeScript register hook:

node -r coffeescript/register examples/raw.coffee
node -r coffeescript/register examples/client.coffee
node -r coffeescript/register examples/keyboard.coffee
node -r coffeescript/register examples/cli-dashboard.coffee

`cli-dashboard.coffee` also accepts optional positional arguments:

node -r coffeescript/register examples/cli-dashboard.coffee <host> <udp-port>

## Python examples

Python 3 is required.

python3 examples/python.py
python3 examples/instanssi.py

`instanssi.py` runs an infinite loop until interrupted:

Ctrl+C

## WebSocket browser example

1. Start server (`npm start`).
2. Open `examples/websocket.html` in a browser.
3. Optional query params:

examples/websocket.html?host=127.0.0.1&port=9910
13 changes: 7 additions & 6 deletions examples/cli-dashboard.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,11 @@


dgram = require('dgram')

tty = require('tty')
readline = require('readline')
process.stdin.resume()
tty.setRawMode(true)
readline.emitKeypressEvents(process.stdin)
if process.stdin.isTTY
process.stdin.setRawMode(true)


randInt = (min, max) ->
Expand Down Expand Up @@ -46,7 +47,7 @@ class EffectClient
@packet.push b

send: ->
buf = new Buffer @packet
buf = Buffer.from @packet
@client.send buf, 0, buf.length, @port, @ip
@reset()

Expand Down Expand Up @@ -118,8 +119,8 @@ main = ->
min: 0
max: 35
nick: process.env.TAG or "epe"
ip: process.argv[2] or "172.18.12.2"
port: 9909
ip: process.argv[2] or process.env.EFFECTSERVER_HOST or "127.0.0.1"
port: Number(process.argv[3] or process.env.EFFECTSERVER_UDP_PORT or 9909)


player = new Player client
Expand Down
8 changes: 4 additions & 4 deletions examples/client.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ class EffectPlayer
@position = @program.length
@udp = dgram.createSocket "udp4"

@buf = new Buffer [
@buf = Buffer.from [
1 # spec version
, 1 # Type. 1 means light
, 0 # light id
Expand All @@ -54,7 +54,7 @@ class EffectPlayer
@buf[4] = color.r
@buf[5] = color.g
@buf[6] = color.b
@udp.send @buf, 0, @buf.length, 9909, "172.18.12.2"
@udp.send @buf, 0, @buf.length, @port, @host

loop: =>

Expand Down Expand Up @@ -87,8 +87,8 @@ if require.main is module
# recorder.pause 1000

player = new EffectPlayer
host: "127.0.0.1"
port: 9909
host: process.env.EFFECTSERVER_HOST or "127.0.0.1"
port: Number(process.env.EFFECTSERVER_UDP_PORT or 9909)
program: recorder.program

player.loop()
Expand Down
11 changes: 8 additions & 3 deletions examples/instanssi.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
#!/usr/bin/python
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import socket
import time
import os


class Instanssi(object):
Expand Down Expand Up @@ -52,7 +53,11 @@ def send(self):



valot = Instanssi("instanssilainen", "172.18.12.2", 9909)
host = os.environ.get("EFFECTSERVER_HOST", "127.0.0.1")
port = int(os.environ.get("EFFECTSERVER_UDP_PORT", "9909"))
nick = os.environ.get("TAG", "instanssilainen")

valot = Instanssi(nick, host, port)


# Sinistä kansalle. Aseta kaikki valot sinisiksi
Expand All @@ -78,6 +83,6 @@ def send(self):
i += 1
i = i % 36

print i
print(i)


16 changes: 10 additions & 6 deletions examples/keyboard.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@
# Execute with Node.js and CoffeeScript
###



tty = require('tty')
readline = require('readline')
dgram = require('dgram')

process.stdin.resume()
tty.setRawMode(true)
readline.emitKeypressEvents(process.stdin)
if process.stdin.isTTY
process.stdin.setRawMode(true)


class RGB
Expand All @@ -34,7 +34,7 @@ class RGB
@packet.push b

send: ->
buf = new Buffer @packet
buf = Buffer.from @packet
console.log buf
@client.send buf, 0, buf.length, @port, @ip
@reset()
Expand Down Expand Up @@ -71,7 +71,11 @@ mapping =
n: 27
m: 28

rgb = new RGB "esa", "172.18.12.2", 9909
rgb = new RGB(
process.env.TAG or "esa"
process.env.EFFECTSERVER_HOST or "127.0.0.1"
Number(process.env.EFFECTSERVER_UDP_PORT or 9909)
)

rgb.set 1, 255, 0, 0
console.log rgb.packet
Expand Down
8 changes: 6 additions & 2 deletions examples/python.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#!/usr/bin/python
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Yksinkertainen UDP-paketti Instanssin valojen ohjailuun Pythonilla.
Expand All @@ -21,6 +21,7 @@


import socket
import os

udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

Expand Down Expand Up @@ -58,5 +59,8 @@
])


udp_socket.sendto(packet, ('172.18.12.2', 9909))
host = os.environ.get("EFFECTSERVER_HOST", "127.0.0.1")
port = int(os.environ.get("EFFECTSERVER_UDP_PORT", "9909"))

udp_socket.sendto(packet, (host, port))

6 changes: 4 additions & 2 deletions examples/raw.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@

dgram = require('dgram')
client = dgram.createSocket("udp4")
host = process.env.EFFECTSERVER_HOST or "127.0.0.1"
port = Number(process.env.EFFECTSERVER_UDP_PORT or 9909)

message = new Buffer [
message = Buffer.from [
1 # spec version

, 1 # Type. 1 means light
Expand All @@ -29,7 +31,7 @@ message = new Buffer [
]


client.send message, 0, message.length, 9909, "172.18.12.2", (err, bytes) ->
client.send message, 0, message.length, port, host, (err, bytes) ->
console.log "sent"
console.log err, bytes

Expand Down
7 changes: 4 additions & 3 deletions examples/websocket.html
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,9 @@
<body>
<script>
const lightCount = 36;
const host = "127.0.0.1";
const port = "9910";
const query = new URLSearchParams(window.location.search);
const host = query.get("host") || "127.0.0.1";
const port = query.get("port") || "9910";

var socket = new WebSocket("ws://"+host+":"+port);
var timeout = undefined;
Expand Down Expand Up @@ -83,7 +84,7 @@

<p>Ammutaan 10ms välein valoja WebSocketin yli effectserverille!</p>
<p>Varoitus: Webbiselaimet saattavat tiputtaa websocket-yhteyksien lähetysmääriä mikäli paljon yhteyksiä auki, tai effectserver ja tämä sivu ovat samalla selaimella auki, tai tämä sivu ei ole aktiivisena välilehtenä.</p>
<div id="content"/>
<div id="content"></div>

</body>
</html>
Loading