我在循环中有问题,Lua中的表
这里是变量knx
的表(现在它是静态的)
regTable = {
{ RegEddr=3027, count=2, regType="float", knx="1/1/1"},
{ RegEddr=3029, count=2, regType="float", knx="1/1/2"},
{ RegEddr=3031, count=2, regType="float", knx="1/1/3"},
{ RegEddr=2999, count=2, regType="float", knx="1/1/4"},
{ RegEddr=3001, count=2, regType="float", knx="1/1/5"},
{ RegEddr=3003, count=2, regType="float", knx="1/1/6"},
{ RegEddr=3109, count=2, regType="float", knx="1/1/7"},
{ RegEddr=3083, count=2, regType="float", knx="1/1/8"},
{ RegEddr=3059, count=2, regType="float", knx="1/1/9"},
{ RegEddr=3203, count=4, regType="int64", knx="1/1/10"},
}
function readRegisters()
for idx, register in pairs(regTable) do
if register.regType=="int" then
valueInt = mb:readregisters(register.RegEddr)
grp.write(register.knx, valueInt)
elseif register.regType=="float" then
value1, value2 = mb:readregisters(register.RegEddr,register.count)
if value1 then
valueFloat = bit.lshift(value1, 16) + value2
valueFloat = lmcore.inttohex(valueFloat, 4)
valueFloat = knxdatatype.decode(valueFloat, dt.float32)
grp.write(register.knx, valueFloat)
end
elseif register.regType=="int64" then
valueInt1, valueInt2, valueInt3, valueInt4 = mb:readregisters(register.RegEddr,register.count)
if valueInt4 then
valueInt64 = valueInt4
log(valueInt64)
grp.write(register.knx, valueInt64)
end
end
end --end for
end --end function
从另一个脚本调用函数readRegisters()
所以我有地址列表,但我不知道用户需要多少个地址。如果是10或100.这就是为什么拥有地址列表而不是最佳的原因而是带有+1步的动态列表
1/1/1
1/1/2
...
1/1/255
有可能帮我创建如何动态地将地址变量knx
添加到此表中吗?
答案 0 :(得分:1)
您需要一个寄存器分配器功能,该功能会考虑最后一个寄存器的地址和大小。此分配器将在您请求时动态创建新寄存器。
local startAddr = 3000
local sizes = {float = 2, int = 2, int64 = 4}
local registers = {}
local function allocRegister(type)
if sizes[type] == nil then
error'invalid register type'
end
local n = #registers
local addr
if n == 0 then -- If this is the first register, use the starting address.
addr = startAddr
else -- Determine the next starting address based on the last register's address & size.
addr = registers[n].addr + registers[n].count
end
table.insert(registers, { addr = addr, count = sizes[type], type = type, knx = '1/1/' .. n + 1 })
end
-- Example usage:
allocRegister'float'
allocRegister'int64'
allocRegister'int'
-- Resulting table:
{
{ addr = 3000, count = 2, knx = "1/1/1", type = "float" },
{ addr = 3002, count = 4, knx = "1/1/2", type = "int64" },
{ addr = 3006, count = 2, knx = "1/1/3", type = "int" }
}
您也可以在循环中使用此功能。以下循环将创建一个非常类似于您问题中的寄存器表。
for i=1, 9 do allocRegister'float' end
allocRegister'int64'
编辑:以下代码应足以说明如何解决您的问题。
local sizes = {float = 2, int = 2, int64 = 4}
local registers = {}
local usedSpace = {}
local function allocRegisters(t)
for i=1, #t do
local addr, size = t[i].addr, sizes[t[i].type]
if size == nil then
error('invalid register type: ' .. t[i].type)
end
-- Check if there's free space for this register.
for j=addr, addr+size-1 do
if usedSpace[j] then
error('address already in use: ' .. addr)
end
end
-- Mark the space for this register as used.
for j=addr, addr+size-1 do
usedSpace[j] = true
end
-- Copy the register into the registers table, setting knx by using the length of the table.
table.insert(registers, { addr = addr, count = size, type = t[i].type, knx = '1/1/' .. #registers + 1})
end
end
-- Example usage:
allocRegisters {
{ addr = 3000, type = 'float' },
{ addr = 3003, type = 'int' },
{ addr = 3009, type = 'int64' }
}
答案 1 :(得分:0)
所以你想动态创建regTable,knx被动态生成为'1/1 / n',其中n是创建顺序。据推测,您还希望根据寄存器类型自动计算计数。看起来地址可以按任何顺序分配,但它们必须与寄存器类型大小一致。那怎么样:
local counts = {float = 2, int = 2, int64 = 4}
local regTable = {}
local function newRegister(addr, regType)
local count = counts[regType]
if count == nil then
error 'invalid register type'
end
checkAddrVsCount(addr, count) -- verify that addr is ok
local tableSize = #regTable
knx = '1/1/' .. (tableSize+1)
regTable.insert {RegEddr=addr, count=count, regType=regType, knx=knx}
end
checkAddrVsCount(addr, count)
检查addr是否有效。对于示例,
RegEddr=addr
的条目,则错误(addr已在表中)