DMX.set with more options - Christian_EWW - 11.08.2020
I'm trying to modify the DMX sample my goal would be to create a set method where I have a parameter for the transition time.
I could use dmxhandler.channels in the resident script and manipulate the target and ticks value, but I don't like this idea.
I would be nicer to have a function within the user.dmx.
What I don't understand is how the data from storage.exec('lset', key, chan - 1, val) gets processed to land in the self.channels, so that I can modify it to pass not only the target value but also a transition time?
Thank's
Christian
RE: DMX.set with more options - admin - 11.08.2020
Try this, untested so might not work
Use DMX.settransition to set value and transition time for a given channel.
Code: local luadmx = require('luadmx')
module('DMX', package.seeall)
local DMX = {}
-- default params
local defaults = {
-- storage key
skey = 'dmx_line_1',
-- RS-485 port
port = '/dev/RS485',
-- number of calls per second
resolution = 20,
-- total number of channels to use
channels = 3,
-- default transition time in seconds, does not include DMX transfer time
transition = 2,
}
local tsuffix = '_transition'
-- match range
local function range(val, min, max)
return min <= val and val <= max
end
-- value setter
function set(chan, val, skey)
skey = skey or defaults.skey
chan = tonumber(chan) or 0
val = tonumber(val) or -1
-- validate channel number and value
if range(chan, 1, 512) and range(val, 0, 255) then
storage.exec('lset', skey, chan - 1, val)
end
end
-- value setter
function settransition(chan, val, tr, skey)
local tkey
skey = skey or defaults.skey
chan = tonumber(chan) or 0
val = tonumber(val) or -1
tr = tonumber(val) or -1
-- validate channel number and value
if range(chan, 1, 512) and range(val, 0, 255) and range(tr, 0, 255) then
tkey = skey .. tsuffix
storage.exec('lset', skey, chan - 1, val)
storage.exec('lset', tkey, chan - 1, tr)
end
end
-- value getter
function get(chan, skey)
local res, val
skey = skey or defaults.skey
chan = tonumber(chan) or 0
-- validate channel number and value
if chan >= 1 and chan <= 512 then
res = storage.exec('lrange', skey, chan - 1, chan - 1)
if type(res) == 'table' then
val = tonumber(res[ 1 ])
end
end
return val
end
-- DMX init, returns new DMX object
function init(params)
local n, k, v, _
-- create metatable and set user parameters
n = setmetatable({}, { __index = DMX })
n.params = params or {}
_, n.conn = pcall(require('redis').connect)
-- merge parameters that are set by user
for k, v in pairs(defaults) do
if n.params[ k ] == nil then
n.params[ k ] = v
end
end
n:reset()
return n
end
function DMX:reset()
local params, skey, tkey, transition, err
params = self.params
skey = params.skey
tkey = skey .. tsuffix
transition = params.transition
self.dm, err = luadmx.open(params.port)
-- error while opening
if err then
os.sleep(1)
error(err)
end
-- set channel count
self.dm:setcount(params.channels)
-- calculate sleep time
self.sleep = 1 / params.resolution
-- reset channel map
self.channels = {}
-- empty channel value map
self.conn:ltrim(skey, 1, 0)
self.conn:ltrim(tkey, 1, 0)
-- fill channel map
for chan = 1, params.channels do
self.channels[ chan ] = { current = 0, target = 0, ticks = 0 }
-- turn off by default, set default transition
self.conn:lpush(skey, 0)
self.conn:lpush(tkey, transition)
self.dm:setchannel(chan, 0)
end
end
-- get new values
function DMX:getvalues()
local skey, tkey, max, channels, values, transition, val, tr, ticks
skey = self.params.skey
tkey = skey .. tsuffix
max = self.params.channels
channels = self.channels
values = self.conn:lrange(skey, 0, max - 1) or {}
transitions = self.conn:lrange(tkey, 0, max - 1) or {}
-- check for new values for each channel
for chan = 1, max do
val = tonumber(values[ chan ]) or 0
tr = tonumber(transitions[ chan ]) or 0
ticks = math.max(1, tr * self.params.resolution)
-- target value differs, set transcation
if val ~= channels[ chan ].target then
channels[ chan ].target = val
channels[ chan ].delta = (channels[ chan ].target - channels[ chan ].current) / ticks
channels[ chan ].ticks = ticks
end
end
end
-- main loop handler
function DMX:run()
self:getvalues()
-- transition loop
for i = 1, self.params.resolution do
self:step()
self.dm:send()
os.sleep(self.sleep)
end
end
-- single transition step
function DMX:step()
local chan, channels, t
channels = self.channels
-- transition for each channel
for chan = 1, self.params.channels do
t = channels[ chan ].ticks
-- transition is active
if t > 0 then
t = t - 1
channels[ chan ].current = channels[ chan ].target - channels[ chan ].delta * t
channels[ chan ].ticks = t
self.dm:setchannel(chan, channels[ chan ].current)
end
end
end
RE: DMX.set with more options - Christian_EWW - 11.08.2020
Thanks a lot, sems to work.
Line 150 should be: ticks = math.max(1, tr * self.params.resolution)
|