我使用 NVIDIA UI Composer Studio 构建了一个仪表集群。 为了控制动画,它使用 Lua 脚本语言。现在我对 Lua 还很陌生,我的问题如下:
我在 Lua 中有以下代码序列来控制我的车速表:
self.vehicleSpeedData = {}
-- 这里放了很多价值观
function self.speedSim( inFrame, theController )
local timeInSec, dummy
timeInSec, dummy = getElapsedTime()
-- data based on 60fps
actualFrameNumber = math.floor(timeInSec * 60)
local theSample = ((actualFrameNumber-1) % #self.vehicleSpeedData) + 1
theController.value = self.vehicleSpeedData[theSample] *0.06
结束
本例中的数组为空。正如您所看到的,该函数读出数组的值。
但是我需要的是,我可以从外部源(例如 RS232 或 CAN 模拟)获取这些数据...我想尝试的是,如果我可以将 C# 中的数据放入 Lua 脚本中。
很难解释我到底想要什么。我的想法是,上面的 Lua 脚本监听并读取我在 C# 中从数据源动态读取的数据。
非常感谢您的帮助。这项工作是为了我的学士学位,我在这一点上停留了很长时间,我几乎没有想法了。
这一切都取决于 Nvidia 向用户公开的内容(就 API 和 Lua 基础库而言)。
假设它可用,您可以使用
io.read
从另一个源读取数据文件(例如 csv),然后自己将其解析到表中。如果您可以预处理文件以获得有效的 Lua 语法(例如,在前面添加 return {
,用 ,
分隔值,并以 }
结尾,您可以直接使用 loadstring 加载字符串)。
如果允许,您可以使用外部库与 RS232、Excel、套接字等接口。
PS:这是Lua而不是LUA(不是缩写词,而是Moon的葡萄牙语名词;))
编辑:示例 mkfifo
所以在 Linux 中它是这样的:用
mkfifo fff
创建一个 fifo 并给它一些 echo ' '> fff 以防止 Lua 阻塞。
在 Lua 中:
fh=io.open('fff','rb')
while true do
res = fh:read()
if res then
print(res)
end
end
无论什么猫喜欢fff(例如
cat 10 > fff
)都会在Lua中出现。这样您就可以读出任何可用的值并在每次运行函数时使用它们。
另一种选择是使用标准输入,但我不确定这个作曲家是否允许你。
我希望你的学士学位能顺利毕业,但这个答复晚了 1.5 年。 :) 尽管如此:
作为 UI Composer 团队的成员和 Lua 脚本编写者,我经常使用的一种将外部数据和事件异步传输到运行时的技术是使用 Lua Socket 库。我在其之上编写了一个抽象层作为 UIC 行为。
-- Expected message structure:
-- "<numbytes>,<optionaltag>\n<bytesofmessage>"
-- e.g. "11,simple\nHello World"
-- e.g. "40,\nThis has no tag,\nbut does have a newline"
local ok,socket = pcall(require,'socket')
if not ok then
output("Error loading socket: "..socket)
else
local output = output or print
local sscallbacks = {} -- indexed by simplesocket instance, then tag
SimpleSocket = {}
local SSMeta = {}
SSMeta.__index=SSMeta
function SimpleSocket:server(port,ip,timeout)
return self:create('server',port,ip,timeout)
end
function SimpleSocket:client(port,ip,timeout)
return self:create('client',port,ip,timeout)
end
function SimpleSocket:create(kind,port,ip,timeout)
if not port then port = 51423 end
if not ip then ip = '*' end
if not timeout then timeout = 10 end
local ss = setmetatable({
kind = kind,
ip = ip,
port = port,
timeout = timeout/1000,
queue = {}
},SSMeta)
sscallbacks[ss] = {}
return ss
end
function SSMeta:destroy()
if self.socket then self.socket:close() end
callbacks[self] = nil
end
function SSMeta:onData(callback,tag)
self:setCallback('handler',callback,tag)
end
function SSMeta:toEncode(callback,tag)
self:setCallback('encoder',callback,tag)
end
function SSMeta:toDecode(callback,tag)
self:setCallback('decoder',callback,tag)
end
function SSMeta:setCallback(type,callback,tag)
if not tag then tag = "" end
if not sscallbacks[self][tag] then sscallbacks[self][tag] = {} end
sscallbacks[self][tag][type] = callback
end
function self:onUpdate()
self:sendQueuedMessages()
self:receiveMessages()
end
function SSMeta:createSocket()
output("Creating new "..self.kind.." socket to "..self.ip..":"..self.port)
if self.kind=='server' then
self.socket = assert(socket.bind(self.ip,self.port))
self.socket:settimeout(self.timeout)
else
self.socket = assert(socket.connect(self.ip,self.port))
end
end
-- Attempts to send all messages from the queue
function self:sendQueuedMessages()
for ss,_ in pairs(sscallbacks) do
while ss.queue[1] do
if ss:sendMessage(message[1]) then
table.remove(ss.queue,1)
else
-- don't attempt any later messages, since ordering may be important
return
end
end
end
end
function self:receiveMessages()
for ss,callbacks in pairs(sscallbacks) do
if ss.kind=='client' then
if not ss.socket then ss:createSocket() end
ss.socket:settimeout(0) -- non-blocking for first byte
local char1, err = ss.socket:receive(1)
ss.socket:settimeout(ss.timeout) -- go back to blocking
if not char1 then
-- probably just timed out
else
local header, err = ss.socket:receive('*l')
if not header then
output(err)
else
header = char1..header
local comma = header:find(',')
local bytes = tonumber(header:sub(1,comma-1))
local tag = header:sub(comma+1)
local data,err = ss.socket:receive(bytes)
if not data then
output(err)
else
if callbacks[tag] and callbacks[tag].decoder then
data = callbacks[tag].decoder(data)
elseif callbacks[true] and callbacks[true].decoder then
data = callbacks[true].decoder(data)
end
if callbacks[tag] and callbacks[tag].handler then
callbacks[tag].handler(data)
elseif callbacks[true] and callbacks[true].handler then
callbacks[true].handler(data)
end
end
end
end
end
end
end
function SSMeta:send(data,tag)
return self:sendMessage(self:encodeMessage(data,tag))
end
function SSMeta:ensureSend(data,tag)
local message = self:encodeMessage(data,tag)
if not self:sendMessage(message) then
table.insert(self.queue,message)
end
end
-- Internal only; use send() or ensureSend()
function SSMeta:sendMessage(formattedMessage)
if not self.socket then self:createSocket() end
if not self.client then self.client = self.socket:accept() end
if self.client then
local lastbyte,err = self.client:send(formattedMessage)
if lastbyte then
-- TODO: verify that all bytes were sent
return true
else
output(err)
self.client:close()
self.client = nil
end
else
-- No client connected before the timeout
end
end
function SSMeta:encodeMessage(data,tag)
data = tostring(data)
local callbacks = sscallbacks[self]
if callbacks[tag] and callbacks[tag].encoder then
data = callbacks[tag].encoder(data)
elseif callbacks[true] and callbacks[true].encoder then
data = callbacks[true].encoder(data)
end
return tostring(#data)..","..(tag or "").."\n"..data
end
end
这允许多个不同的系统在同一套接字上进行通信,具有不同的标记通信,并且可能使用不同的编码器/解码器来序列化/反序列化数据。
在接收端,它的用法如下:
local ss = require 'SimpleSocket'
local client = ss:client()
client:onData(function(d) print("Client got *: "..d) end,true)