Tag Archives: Logic Machine

LogicMachine telnet user script

The following code enables you to open a telnet connection and send commands. I use it to connect to my Pioneer sound system. Add it to a user script.


-- send Telnet command

function telnet(host, port, command)
local socket = require("socket")
local tcp = assert(socket.tcp())
res, err = tcp:connect(host, port)
res, err = tcp:send(command)

while true do
local s, status, threebytes = tcp:receive(3)
if status == "closed" then break end


All you need to do now is call the function from your KNX-Object script. Example:

telnet('', 8102, 'PF\r\n\r\nclose\r\n\r\n')

The PF command tells my Pioneer to turn off. I’m not sure if a close command is necessary, but all the returns are. The IP address and port have to be changed to what you need.

Turn all DMX LED lights on/off using the Logic Machine reactor

We have quite a few DMX based LED lighting sources. I use the eldoled lineardrive 720D to do the controling part. The following script enables me to turn the LEDs on/off, all at once.

-- This software may be used and distributed according to the terms of the
-- GNU General Public License version 3, incorporated herein by reference.

-- define group address
dmxchan = 12
dmxon = 255
dmxoff = 0
-- address of all on/off group
groupvalue = '1/2/0'

-- addresses of groups that should be switched including the all on/off group
lights = {'1/2/0', '1/1/0', '1/1/2', '1/1/3', '1/1/4', '1/1/5', '1/1/6', '1/1/7', '1/1/8'}

-- get value of object with group address
value = grp.getvalue(groupvalue)

if (value == false) then
  -- channel value set to 255
  for i = 1, dmxchan, 1 do
    DMX.set(i, dmxon)
  -- change groups to true
  for index, value in ipairs(lights) do
    grp.write(value, true)

  log('Light on')
  -- channel 1 value set to 0
  for i = 1, dmxchan, 1 do
    DMX.set(i, dmxoff)
  -- change groups to false
  for index, value in ipairs(lights) do
    grp.write(value, false)
  log('Light off')

I created an “event based script” in the Logic Machine to add this code. The address I monitor is 1/1/1 which is the group that turns all lights on/off in the KNX push buttons.

Logic Machine - group address for DMX

DMX on the Logic Machine

To get the DMX control of the Logic Machine one needs to get two scripts running. The first is a “handler” that needs to be added as a resident script:

Logic Machine - DMX handler resident script

-- This software may be used and distributed according to the terms of the
-- GNU General Public License version 3, incorporated herein by reference.

if not d then
  d = DMX:init({
    channels = 16,
    transition = 1,
  log('DMX initialized')

-- reset custom DMX RGB color settings to "off" (0), comment out if not needed
  storage.set('DMXrgbred', 0)
  storage.set('DMXrgbgreen', 0)
  storage.set('DMXrgbblue', 0)
  log('Reset RGB colors')


and the second are the common functions, that you can just add to the end of the current common functions.

-- This code is copyright of openrb.com
-- Open Source but != free 

DMX = {
  -- default params
  defaults = {
    -- storage key
    skey = 'dmx_chan_',
    -- RS-485 port
    port = '/dev/ttyAPP2',
    -- number of calls per second
    resolution = 20,
    -- total number of channels to use
    channels = 16,
    -- transition time in seconds, does not include DMX transfer time
    transition = 2,
  -- value setter
  set = function(i, v)
    -- validate channel number
    if type(i) == 'number' and i >= 1 and i < = 512 then
      -- validate channel value
      if type(v) == 'number' and v >= 0 and v < = 255 then
        storage.set(DMX.defaults.skey .. i, v)

-- DMX init, returns new DMX object
function DMX:init(params)
  log('starting DMX')

  local n = setmetatable({}, { __index = DMX })
  local k, v

  -- set user parameters
  n.params = params

  -- copy parameters that are set by user
  for k, v in pairs(DMX.defaults) do
    if n.params&#91; k &#93; == nil then
      n.params&#91; k &#93; = v


  return n

function DMX:reset()
  local err, chan
  log('resetting DMX')
  self.dm, err = luadmx.open(self.params.port)

    -- error while opening
  if err then

  -- set channel count

  -- number of transaction ticks
  self.ticks = math.max(1, self.params.transition * self.params.resolution)

  -- calculate sleep time
  self.sleep = 1 / self.params.resolution

  -- reset channel map
  self.channels = {}

  -- fill channel map
  for chan = 1, self.params.channels do
    self.channels&#91; chan &#93; = { current = 0, target = 0, ticks = 0 }

    -- turn off by default
    storage.set(self.params.skey .. chan, 0)
    self.dm:setchannel(chan, 0)

-- get new values
function DMX:getvalues()
  local chan, val
  --log('getting DMX values')
  -- check for new values for each channel
  for chan = 1, self.params.channels do
    val = storage.get(self.params.skey .. chan)

    -- target value differs, set transcation
    if val ~= self.channels&#91; chan &#93;.target then
      self.channels&#91; chan &#93;.target = val
      self.channels&#91; chan &#93;.delta = (self.channels&#91; chan &#93;.target - self.channels&#91; chan &#93;.current) / self.ticks
      self.channels&#91; chan &#93;.ticks = self.ticks

-- main loop handler
function DMX:run()
  local i, bs, bm, as, am, delta
  local res = self.params.resolution

  if not self.calibrated then
    bs, bm = os.microtime()

  -- transition loop
  for i = 1, res do

    -- wait until next step

  -- calibrate delay loop to match 1 second
  if not self.calibrated then
    as, am = os.microtime()
    delta = (as - bs) + (am - bm) / 1000000

    if delta > 1.05 then
      self.sleep = self.sleep - math.max(10, self.sleep / res)
      self.calibrated = true

-- single transition step
function DMX:step()
  local chan, t

  -- transition for each channel
  for chan = 1, self.params.channels do
    t = self.channels[ chan ].ticks

    -- transition is active
    if t > 0 then
      t = t - 1

      self.channels[ chan ].current = self.channels[ chan ].target - self.channels[ chan ].delta * t
      self.channels[ chan ].ticks = t

      self.dm:setchannel(chan, self.channels[ chan ].current)

Logic Machine re:actor videos

I bought a Logic Machine from openrb.com a few weeks ago. At about 1.100€ it is not very cheap, but it contains quite a few features that, if bought separately, would have been a lot more expensive. I am going to use it in our flat to do the following:

  1. as a KNX gateway (separate for at least 400€)

  2. DMX or DALI controller (separate for at least 600€)

  3. Home automation visualization (PC and Touch, go for about 1.700€)

  4. Logging

  5. Logic

  6. Digital/Analog inputs and outputs

Nice to have is the enocean chip. If for any reason I need to add wireless sensors or actuators, this will help a lot.

Right now it is not connected to the KNX bus, but I imported a few objects from the ETS4 software (OPC export). Then I used Sweet Home 3D to create a nice 3D view of the flat. Using GIMP I created some nice transparent lighting elements.

To see what I then did with the re:actor check out the following two videos: