Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlan Aguiar <alanjas@hotmail.com>2012-10-18 01:09:19 (GMT)
committer Alan Aguiar <alanjas@hotmail.com>2012-10-18 01:09:19 (GMT)
commitbf90188aa6b9d309d40cde736db2f81df68856e6 (patch)
treec57cf8c31f1f039f22c9500015583d78ea3ca1eb
parente1e2489a88e977c77d7ba47ef1c2c5763f5cd012 (diff)
replace butia_support with support from TurtleBots 17
-rw-r--r--lib/support/Makefile17
-rw-r--r--lib/support/bobot-server.lua227
-rw-r--r--lib/support/bobot.lua55
-rw-r--r--lib/support/bobot_server/bobot-server-http.lua211
-rw-r--r--lib/support/bobot_server/bobot-server-process.lua176
-rw-r--r--lib/support/bobot_server/bobot.pngbin0 -> 10277 bytes
-rw-r--r--lib/support/bobot_server/butia/butia.htm17
-rw-r--r--lib/support/bobot_server/butia/butia_http.lua32
-rw-r--r--lib/support/bobot_server/butia/command.htm36
-rw-r--r--lib/support/bobot_server/butia/describeButia.htm88
-rw-r--r--lib/support/bobot_server/butia/header.htm10
-rw-r--r--lib/support/bobot_server/butia/images/btar_dn.gifbin0 -> 303 bytes
-rw-r--r--lib/support/bobot_server/butia/images/btar_lft.gifbin0 -> 279 bytes
-rw-r--r--lib/support/bobot_server/butia/images/btar_rgt.gifbin0 -> 283 bytes
-rw-r--r--lib/support/bobot_server/butia/images/btar_up.gifbin0 -> 312 bytes
-rw-r--r--lib/support/bobot_server/butia/images/butiaRobot3.pngbin0 -> 80308 bytes
-rw-r--r--lib/support/bobot_server/butia/images/clase07.jpgbin0 -> 20771 bytes
-rw-r--r--lib/support/bobot_server/butia/sensors.htm40
-rw-r--r--lib/support/bobot_server/butia/view.htm10
-rw-r--r--lib/support/bobot_server/dumptemplate.txt11
-rw-r--r--lib/support/bobot_server/dumptemplate_descr.txt37
-rw-r--r--lib/support/bobot_server/dumptemplate_descr_row.txt20
-rw-r--r--lib/support/bobot_server/favicon.icobin0 -> 1406 bytes
-rw-r--r--lib/support/bobot_server/http-util.lua41
-rw-r--r--lib/support/bobot_server/indextemplate.txt16
-rw-r--r--lib/support/drivers/admin.lua11
-rw-r--r--lib/support/drivers/ax.lua118
-rw-r--r--lib/support/drivers/boot.lua11
-rw-r--r--lib/support/drivers/boton.lua19
-rw-r--r--lib/support/drivers/butia.lua39
-rw-r--r--lib/support/drivers/buzzer.lua51
-rw-r--r--lib/support/drivers/debug.lua39
-rw-r--r--lib/support/drivers/display.lua99
-rw-r--r--lib/support/drivers/dist.lua25
-rw-r--r--lib/support/drivers/dynamix.lua34
-rw-r--r--lib/support/drivers/gas.lua20
-rw-r--r--lib/support/drivers/grises.lua19
-rw-r--r--lib/support/drivers/hotplug/button.lua32
-rw-r--r--lib/support/drivers/hotplug/distanc.lua32
-rw-r--r--lib/support/drivers/hotplug/gpio.lua19
-rw-r--r--lib/support/drivers/hotplug/grey.lua32
-rw-r--r--lib/support/drivers/hotplug/light.lua32
-rw-r--r--lib/support/drivers/hotplug/port.lua19
-rw-r--r--lib/support/drivers/hotplug/tilt.lua19
-rw-r--r--lib/support/drivers/hotplug/vibra.lua19
-rw-r--r--lib/support/drivers/lback.lua21
-rw-r--r--lib/support/drivers/led.lua17
-rw-r--r--lib/support/drivers/ledA.lua46
-rw-r--r--lib/support/drivers/ledR.lua31
-rw-r--r--lib/support/drivers/ledV.lua31
-rw-r--r--lib/support/drivers/leds.lua43
-rw-r--r--lib/support/drivers/luz.lua21
-rw-r--r--lib/support/drivers/magnet.lua21
-rw-r--r--lib/support/drivers/motor.lua42
-rw-r--r--lib/support/drivers/motorTm.lua47
-rw-r--r--lib/support/drivers/motores.lua48
-rw-r--r--lib/support/drivers/motorin.lua28
-rw-r--r--lib/support/drivers/motors.lua70
-rw-r--r--lib/support/drivers/move.lua16
-rw-r--r--lib/support/drivers/pnp.lua0
-rw-r--r--lib/support/drivers/pote.lua16
-rw-r--r--lib/support/drivers/puerta.lua31
-rw-r--r--lib/support/drivers/sec.lua87
-rw-r--r--lib/support/drivers/sensor.lua52
-rw-r--r--lib/support/drivers/stmtr.lua46
-rw-r--r--lib/support/drivers/temp.lua28
-rw-r--r--lib/support/drivers/temp_lubot.lua20
-rw-r--r--lib/support/lib/bobot_baseboard.lua393
-rw-r--r--lib/support/lib/bobot_device.lua216
-rw-r--r--lib/support/lib/comms_chotox.lua39
-rw-r--r--lib/support/lib/comms_serial.lua94
-rw-r--r--lib/support/lib/comms_usb.lua99
-rwxr-xr-xlib/support/lib/libluausb.sobin0 -> 17457 bytes
-rwxr-xr-xlib/support/lib/lua_serialcomm.sobin0 -> 11599 bytes
-rwxr-xr-xlib/support/lib/mime/core.sobin0 -> 12937 bytes
-rwxr-xr-xlib/support/lib/socket/core.sobin0 -> 44755 bytes
-rwxr-xr-xlib/support/libluausb.sobin0 -> 17457 bytes
-rwxr-xr-xlib/support/luabin0 -> 161497 bytes
-rwxr-xr-xlib/support/lua_serialcomm.sobin0 -> 11599 bytes
-rw-r--r--lib/support/share/ltn12.lua292
-rw-r--r--lib/support/share/mime.lua87
-rw-r--r--lib/support/share/socket.lua133
-rw-r--r--lib/support/share/socket/ftp.lua281
-rw-r--r--lib/support/share/socket/http.lua350
-rw-r--r--lib/support/share/socket/smtp.lua251
-rw-r--r--lib/support/share/socket/tp.lua123
-rw-r--r--lib/support/share/socket/url.lua297
-rw-r--r--lib/support/socket.lua133
-rwxr-xr-xlib/support/socket/core.sobin0 -> 44755 bytes
89 files changed, 5283 insertions, 0 deletions
diff --git a/lib/support/Makefile b/lib/support/Makefile
new file mode 100644
index 0000000..56a5568
--- /dev/null
+++ b/lib/support/Makefile
@@ -0,0 +1,17 @@
+# Makefile para instalar todas las dependencias de lua y bobot
+
+all: dependency
+ @echo bobot listo para usar en XO !
+
+dependency:
+ $(MAKE) -C ../serialcomm/lua_bindings
+ $(MAKE) -C ../lualibusb
+ $(MAKE) -C ../libs/lua-5.1.4 linux
+ $(MAKE) -C ../libs/luasocket
+
+clean:
+ @rm -f *~ *.o drivers/*~
+ $(MAKE) -C ../serialcomm/lua_bindings clean
+ $(MAKE) -C ../lualibusb clean
+ $(MAKE) -C ../libs/lua-5.1.4 clean
+ $(MAKE) -C ../libs/luasocket clean
diff --git a/lib/support/bobot-server.lua b/lib/support/bobot-server.lua
new file mode 100644
index 0000000..fcaa55b
--- /dev/null
+++ b/lib/support/bobot-server.lua
@@ -0,0 +1,227 @@
+#!/usr/bin/lua
+
+--[[
+
+Syntax
+
+ # lua bobot-server.lua [DEBUG] [connection]*
+
+Parameters:
+ DEBUG enables debug printing in bobot
+ connection a list of connection services to attempt. Supported
+ values in bobot (for now) are usb, serial and chotox
+
+If no connection services are provided, defaults to usb and serial.
+
+Examples:
+ Start with debug disabled and the dummy chotox service, only:
+ # lua bobot-server.lua chotox
+
+ Start with debug enabled and the serial services only:
+ # lua bobot-server.lua DEBUG serial
+
+ Start with debug disabled and the usb and serial services (same as default):
+ # lua bobot-server.lua usb serial
+
+--]]
+
+--package.path=package.path..";./bobot_server/?.lua"
+local my_path = debug.getinfo(1, "S").source:match[[^@?(.*[\/])[^\/]-$]] or "./"
+package.path=package.path..";"..my_path.."bobot_server/?.lua;"
+ ..my_path.."lib/?.lua;"..my_path.."?.lua"
+
+--tcp listening address
+local N_PROTOCOLS = 2
+local ADDRESS = "*"
+local PORT_B = 2009 --B is for bobot
+local PORT_H = 2010 --H is for http
+
+local TIMEOUT_REFRESH = 3
+
+local socket = require("socket")
+local process = require("bobot-server-process").process
+local http_serve = require("bobot-server-http").serve
+
+local bobot = require("bobot")
+
+local set_debug
+for i, v in ipairs(arg) do
+ if v=="DEBUG" then
+ set_debug=true
+ table.remove(arg, i)
+ break
+ end
+end
+if set_debug then
+ bobot.debugprint = print
+ bobot.debugprint("Debugging messages enabled")
+else
+ bobot.debugprint = function() end
+end
+
+
+local server_b = assert(socket.bind(ADDRESS, PORT_B))
+local server_h = assert(socket.bind(ADDRESS, PORT_H))
+
+local recvt={[1]=server_b, [2]=server_h}
+
+devices = {}
+
+local function get_device_name(d)
+
+--print("DEVICENAME", d.module, d.hotplug, d.handler)
+ local board_id, port_id = '', ''
+ if #bobot.baseboards>1 then
+ board_id='@'..d.baseboard.idBoard
+ end
+ if d.hotplug then
+ port_id = ':'..d.handler
+ end
+
+ local n=d.module..board_id..port_id
+
+ if not devices[n] then
+ return n
+ end
+
+ local i=2
+ local nn=n.."#"..i
+ while devices[nn] do
+ i=i+1
+ nn=n.."#"..i
+ end
+
+ return nn
+end
+
+local function read_devices_list()
+ bobot.debugprint("=Listing Devices")
+ local bfound
+ devices={}
+ for _, bb in ipairs(bobot.baseboards) do
+ bobot.debugprint("===board ", bb.idBoard)
+ for _,d in ipairs(bb.devices) do
+ local regname = get_device_name(d)
+ devices[regname]=d
+ devices[#devices+1]=d
+ d.name=regname
+ bobot.debugprint("=====module ",d.module," name",regname)
+ end
+ bfound = true
+ end
+ if not bfound then bobot.debugprint("ls:WARN: No Baseboard found.") end
+end
+
+local function split_words(s)
+ local words={}
+
+ for p in string.gmatch(s, "%S+") do
+ words[#words+1]=p
+ end
+
+ return words
+end
+
+local socket_handlers = {}
+setmetatable(socket_handlers, { __mode = 'k' })
+socket_handlers[server_b]=function()
+ local client, err=server_b:accept()
+ if not client then return end
+ bobot.debugprint ("bs:New bobot client", client, client:getpeername())
+ table.insert(recvt,client)
+ socket_handlers[client] = function ()
+ local line,err = client:receive()
+ if err=='closed' then
+ bobot.debugprint ("bs:Closing bobot client", client)
+ for k, v in ipairs(recvt) do
+ if client==v then
+ table.remove(recvt,k)
+ return
+ end
+ end
+ end
+ if line then
+ local words=split_words(line)
+ local command=words[1]
+ if not command then
+ bobot.debugprint("bs:Error parsing line:", line, command)
+ else
+ if not process[command] then
+ bobot.debugprint("bs:Command not supported:", command)
+ else
+ if command=="QUIT" and #recvt>N_PROTOCOLS+1 then
+ client:send("server in use\n")
+ return
+ end
+ local ret = process[command](words) or ""
+ client:send(ret .. "\n")
+ end
+ end
+ end
+ end
+end
+
+socket_handlers[server_h]=function()
+ local client, err=server_h:accept()
+ if not client then return end
+ bobot.debugprint ("bs:New http client", client, client:getpeername())
+ client:setoption ("tcp-nodelay", true)
+ --client:settimeout(5)
+ table.insert(recvt,client)
+ socket_handlers[client] = function ()
+ local ret,err=http_serve(client)
+ if err=='closed' then
+ bobot.debugprint ("bs:Closing http client", client)
+ for k, v in ipairs(recvt) do
+ if client==v then
+ table.remove(recvt,k)
+ return
+ end
+ end
+ end
+ if ret then
+ client:send(ret)
+ end
+ end
+end
+
+function server_refresh ()
+ local refreshed
+ for i, bb in ipairs(bobot.baseboards) do
+ --if bb.refresh and not (bb.comms.type=='serial' and bb.devices) then
+ if bb.refresh and bb.hotplug then
+ if not bb:refresh() then
+ bobot.baseboards[i]=nil
+ end
+ refreshed=true
+ end
+ end
+ if refreshed then read_devices_list() end
+end
+
+function server_init ()
+ bobot.init(arg)
+ read_devices_list()
+end
+
+
+server_init()
+bobot.debugprint("Listening...")
+-- loop forever waiting for clients
+
+while 1 do
+ local recvt_ready, _, err=socket.select(recvt, nil, TIMEOUT_REFRESH)
+ if err=='timeout' then
+ if #bobot.baseboards==0 then
+ server_init ()
+ else
+ server_refresh ()
+ end
+ else
+ local skt=recvt_ready[1]
+ socket_handlers[skt]()
+ end
+end
+
+
+
diff --git a/lib/support/bobot.lua b/lib/support/bobot.lua
new file mode 100644
index 0000000..c7dd062
--- /dev/null
+++ b/lib/support/bobot.lua
@@ -0,0 +1,55 @@
+--[[
+bobot library
+
+Example usage:
+ bobot=require("bobot")
+ bobot.init()
+
+init() can receive a list of connectors to use. Supported values are "usb", "serial" and "chotox".
+For example, to only use de dummy chotox driver, use init({"chotox"})
+If no parameter is provided, behaves like init({"usb","serial"}).
+
+--]]
+
+local my_path = debug.getinfo(1, "S").source:match[[^@?(.*[\/])[^\/]-$]] or "./"
+package.path=package.path..";"..my_path.."lib/?.lua"
+
+local socket=require('socket')
+
+local B = {}
+
+B.debugprint = print --function() end --do not print anything by default
+
+--baseboards[iSerial] = BaseBoard
+--B.baseboards = {}
+
+--Returns number of baseboards detected.
+B.init = function ( comms )
+ if not comms or #comms==0 then comms = {"usb","serial"} end
+
+ B.baseboards={} --flush the baseboard because this function could be call after hardware remove or adition
+
+ local n_boards, n_boards_total = {}, 0
+ local start_time = os.time()
+
+ repeat
+ for _, comm in ipairs(comms) do
+ B.debugprint ("Querying for baseboards:", comm)
+ local comm_lib = require('comms_'..comm)
+ if not comm_lib then
+ B.debugprint("Could not open library:", comm)
+ else
+ comm_lib.type=comm
+ n_boards[comm] = comm_lib.init(B.baseboards)
+ n_boards_total = n_boards_total + n_boards[comm]
+ end
+ end
+ if n_boards_total == 0 then socket.sleep(1) end
+ until n_boards_total > 0 or os.time()-start_time > 3
+
+ return n_boards_total
+end
+
+--B.init()
+
+return B
diff --git a/lib/support/bobot_server/bobot-server-http.lua b/lib/support/bobot_server/bobot-server-http.lua
new file mode 100644
index 0000000..efa239d
--- /dev/null
+++ b/lib/support/bobot_server/bobot-server-http.lua
@@ -0,0 +1,211 @@
+module(..., package.seeall);
+
+local bobot = require("bobot")
+
+--local devices=devices
+local process = require("bobot-server-process").process
+local butia = require("butia/butia_http")
+local util = require("http-util")
+
+local parse_params = util.parse_params
+local load_template = util.load_file
+local find_page = util.find_page
+
+--enable to cache in RAM
+--[[
+local index_template=load_template('indextemplate.txt')
+local dump_template=load_template('dumptemplate.txt')
+local dump_template_descr=load_template('dumptemplate_descr.txt')
+local dump_template_descr_row=load_template('dumptemplate_descr_row.txt')
+--]]
+
+local function check_open_device(d, ep1, ep2)
+ if not d then return end
+ if d.handler then return true end
+ -- if the device is not open, then open the device
+ bobot.debugprint ("Opening", d.name, d.handler)
+ return d:open(ep1 or 1, ep2 or 1) --TODO asignacion de ep?
+end
+
+local html_list_devices = function (params)
+ local ret,comma = "", ""
+ local dsel=params['dsel']
+ for d_name, d in pairs(devices) do
+ local broken=""
+ if not check_open_device(d, ep1, ep2) then
+ broken=" (failed to open)"
+ bobot.debugprint ("bs: WARN! Failure opening", d_name)
+ end
+ if dsel==d_name then
+ ret = ret .. comma .. '<strong>' .. d_name .. broken .. '</strong>'
+ else
+ ret = ret .. comma .. '<a href="/dump.htm?dsel='..d_name..'">'..d_name..broken..'</a>'
+ end
+ comma=", "
+ end
+ return ret
+end
+
+local html_describe_device = function (params)
+ --borrar
+ dump_template_descr_row=load_template('dumptemplate_descr_row.txt')
+
+ local dsel=params['dsel']
+ local command=params['command']
+ if not dsel then return "" end
+
+ local device=devices[dsel]
+
+ if not device then return "<TR><TD>Missing Device!</TD></TR>" end
+ if not device.api then return "<TR><TD>Missing Driver for Device!</TD></TR>" end
+
+ local ret = ""
+ for fname, fdef in pairs(device.api) do
+ local row=dump_template_descr_row
+
+ local result,ok
+ --print ("::",command,fname)
+ if command==fname then
+ --preparar parametros
+ local fparams={}
+ for i,param in ipairs(fdef.parameters) do
+ local rname=param['rname']
+ local rtype=param['rtype']
+ if rtype=="int" or rtype=="number" or rtype=="numeric" then
+ fparams[i]=tonumber(params[rname])
+ else
+ fparams[i]=params[rname]
+ end
+ end
+
+ --ejecutar
+ ok, result= pcall( fdef.call, unpack(fparams) )
+ if not ok then bobot.debugprint ("Error calling", ret) end
+ --imprimir
+ bobot.debugprint ("::::",result)
+ end
+
+ local returns=''
+ local comma=''
+ for i,rets in ipairs(fdef.returns) do
+ returns = returns..comma..rets['rtype']..'&nbsp;'..rets['rname']
+ comma=','
+ end
+ local formfields=''
+ local parameters=''
+ local comma=''
+ for i,rets in ipairs(fdef.parameters) do
+ local rname=rets['rname']
+ formfields=formfields..rname..': <INPUT TYPE="text" NAME="'..rname..'" /><br>'
+ parameters = parameters..comma..rets['rtype']..'&nbsp;'..rname
+ comma=','
+ end
+
+ local rep = {
+ ['COMMAND'] = fname,
+ ['RETURNS'] = returns,
+ ['PARAMETERS'] = parameters,
+ ['RESULT'] = result,
+ ['MODULENAME'] = dsel,
+ ['FORMFIELDS'] = formfields,
+ }
+ local generated_row=string.gsub(row, '<!%-%-(%w+)%-%->', rep)
+
+ ret=ret..generated_row
+
+ end
+
+ return ret
+end
+
+local get_page={}
+setmetatable(get_page, {__index = function(_,page) bobot.debugprint ("======", page);return find_page(page) end})
+get_page["/index.htm"] = function (p)
+ local index_template=load_template('indextemplate.txt')
+
+ local params=parse_params(p)
+ local rep = {
+ ['DATA1'] = params['campo'],
+ ['DATA2'] = tostring(params['unboton'])..', '..tostring(params['otroboton']),
+ }
+ local page=string.gsub(index_template, '<!%-%-(%w+)%-%->', rep)
+ return "HTTP/1.1 200/OK\r\nContent-Type:text/html\r\nContent-Length: "..#page.."\r\n\r\n"..page
+end
+get_page["/"]=get_page["/index.htm"]
+get_page["/dump.htm"] = function (p)
+ --remove this
+ dump_template=load_template('dumptemplate.txt')
+ dump_template_descr=load_template('dumptemplate_descr.txt')
+
+ local params=parse_params(p)
+ local dsel=params['dsel']
+
+ local usetemplate
+ if dsel then
+ usetemplate=dump_template_descr
+ else
+ usetemplate=dump_template
+ end
+
+ local rep = {
+ ['LIST'] = html_list_devices(params),
+ ['MODULENAME'] = dsel or "(empty dsel)",
+ ['ROWS'] = html_describe_device(params),
+ }
+ local page=string.gsub(usetemplate, '<!%-%-(%w+)%-%->', rep)
+ return "HTTP/1.1 200/OK\r\nContent-Type:text/html\r\nContent-Length: "..#page.."\r\n\r\n"..page
+end
+get_page["/favicon.ico"] = function ()
+ local served, err = io.open('bobot_server/favicon.ico', "rb")
+ if served ~= nil then
+ local content = served:read("*all")
+ return "HTTP/1.1 200/OK\r\nContent-Type:image/x-icon\r\nContent-Length: "
+ ..#content.."\r\n\r\n" .. content
+ else
+ bobot.debugprint("Error opening favicon:", err)
+ return default_page()
+ end
+end
+get_page["/bobot.png"] = function ()
+ local served, err = io.open('bobot_server/bobot.png', "rb")
+ if served ~= nil then
+ local content = served:read("*all")
+ return "HTTP/1.1 200/OK\r\nContent-Type:image/png\r\nContent-Length: "
+ ..#content.."\r\n\r\n" .. content
+ else
+ bobot.debugprint("Error opening logo:", err)
+ return default_page()
+ end
+end
+butia.init(get_page)
+
+function serve(skt)
+ local line,err = skt:receive('*l') --read first line, must be GET or POST
+ if err then return nil, err end
+
+ local f,p=string.match(line, '^GET ([%/%.%d%w%-_]+)[%?]?(.-) HTTP/1.1$')
+ if f then
+ repeat
+ --skip headers we don't care
+ line,err=skt:receive()
+ until line=='' or line==nil
+ if err then return end
+ local s=get_page[f](p)
+ return(s..'\r\n')
+ end
+
+ local f,p=string.match(line, '^POST ([%/%.%d%w%-_]+) HTTP/1.1$')
+ if f then
+ local length
+ repeat
+ --skip headers we don't care
+ line,err=skt:receive()
+ length=length or string.match(line, '^Content%-Length%: (%d+)$')
+ until line=='' or line==nil
+ if err then return end
+ local p=skt:receive(tonumber(length))
+ local s=get_page[f](p)
+ return(s..'\r\n')
+ end
+end
+
diff --git a/lib/support/bobot_server/bobot-server-process.lua b/lib/support/bobot_server/bobot-server-process.lua
new file mode 100644
index 0000000..18231cb
--- /dev/null
+++ b/lib/support/bobot_server/bobot-server-process.lua
@@ -0,0 +1,176 @@
+#!/usr/bin/lua
+
+module(..., package.seeall);
+
+local bobot = require("bobot")
+
+--local devices=devices
+--local DEBUG = false
+
+local function check_open_device(d, ep1, ep2)
+ if not d then return end
+ if d.handler or d.name=='pnp' then return true end
+
+ -- if the device is not open, then open the device
+ bobot.debugprint ("Opening", d.name, d.handler)
+ return d:open(ep1 or 1, ep2 or 1) --TODO asignacion de ep?
+end
+
+process = {}
+
+process["INIT"] = function () --to check the new state of hardware on the fly
+ server_init()
+end
+process["REFRESH"] = function () --to check the new state of hardware on the fly
+ --for _, bb in ipairs(bobot.baseboards) do
+ -- bb:refresh()
+ --end
+ server_refresh()
+ return 'ok'
+end
+
+
+process["LIST"] = function ()
+ local ret,comma = "", ""
+ for _, d in ipairs(devices) do
+ ret = ret .. comma .. d.name
+ comma=","
+ end
+ return ret
+end
+
+
+process["LISTI"] = function ()
+ if bobot.baseboards then
+ bobot.debugprint("listing instanced modules...")
+ for _, bb in ipairs(bobot.baseboards) do
+ local handler_size=bb:get_handler_size()
+ for i=1, handler_size do
+ t_handler = bb:get_handler_type(i)
+ bobot.debugprint("handler=", i-1 ," type=" ,t_handler)
+ end
+ end
+ end
+end
+
+
+process["OPEN"] = function (parameters)
+ local d = parameters[2]
+ local ep1= tonumber(parameters[3])
+ local ep2= tonumber(parameters[4])
+
+ if not d then
+ bobot.debugprint("ls:Missing 'device' parameter")
+ return
+ end
+
+ local device = devices[d]
+ if check_open_device(device, ep1, ep2) then
+ return "ok"
+ else
+ return "fail"
+ end
+end
+process["DESCRIBE"] = function (parameters)
+ local d = parameters[2]
+ local ep1= tonumber(parameters[3])
+ local ep2= tonumber(parameters[4])
+
+ if not d then
+ bobot.debugprint("ls:Missing \"device\" parameter")
+ return
+ end
+
+ local device = devices[d]
+ if not check_open_device(device, ep1, ep2) then
+ return "fail"
+ end
+ if not device.api then
+ return "missing driver"
+ end
+
+ local ret = "{"
+ for fname, fdef in pairs(device.api) do
+ ret = ret .. fname .. "={"
+ ret = ret .. " parameters={"
+ for i,pars in ipairs(fdef.parameters) do
+ ret = ret .. "[" ..i.."]={"
+ for k, v in pairs(pars) do
+ ret = ret .."['".. k .."']='"..tostring(v).."',"
+ end
+ ret = ret .. "},"
+ end
+ ret = ret .. "}, returns={"
+ for i,rets in ipairs(fdef.returns) do
+ ret = ret .. "[" ..i.."]={"
+ for k, v in pairs(rets) do
+ ret = ret .."['".. k .."']='"..tostring(v).."',"
+ end
+ ret = ret .. "},"
+ end
+ ret = ret .. "}},"
+ end
+ ret=ret.."}"
+
+ return ret
+end
+process["CALL"] = function (parameters)
+ local d = parameters[2]
+ local call = parameters[3]
+
+ if not (d and call) then
+ bobot.debugprint("ls:Missing parameters", d, call)
+ return
+ end
+
+ local device = devices[d]
+ if not check_open_device(device, nil, nil) then
+ return "fail"
+ end
+
+ if not device.api then return "missing driver" end
+ local api_call=device.api[call];
+ if not api_call then return "missing call" end
+
+ if api_call.call then
+ --local tini=socket.gettime()
+ local ok, ret = pcall (api_call.call, unpack(parameters,4))
+ if not ok then bobot.debugprint ("Error calling", ret) end
+ --print ('%%%%%%%%%%%%%%%% bobot-server',socket.gettime()-tini)
+ return ret
+ end
+end
+process["CLOSEALL"] = function ()
+ if bobot.baseboards then
+ for _, bb in ipairs(bobot.baseboards) do
+ --this command closes all the open user modules
+ --it does not have sense with plug and play
+ bb:force_close_all() --modif andrew
+ end
+ end
+ return "ok"
+end
+process["BOOTLOADER"] = function ()
+ if bobot.baseboards then
+ for _, bb in ipairs(bobot.baseboards) do
+ bb:switch_to_bootloader()
+ end
+ end
+ return "ok"
+end
+process["DEBUG"] = function (parameters) --disable debug mode Andrew code!
+ local debug = parameters[2]
+ if not debug then return "missing parameter" end
+ if debug=="ON" then
+ bobot.debugprint = print --function(...) print (...) end --enable printing
+ elseif debug=="OFF" then
+ bobot.debugprint = function() end --do not print anything
+ end
+ return "ok"
+end
+process["QUIT"] = function ()
+ bobot.debugprint("Requested EXIT...")
+ os.exit()
+ return "ok"
+end
+
diff --git a/lib/support/bobot_server/bobot.png b/lib/support/bobot_server/bobot.png
new file mode 100644
index 0000000..2de1124
--- /dev/null
+++ b/lib/support/bobot_server/bobot.png
Binary files differ
diff --git a/lib/support/bobot_server/butia/butia.htm b/lib/support/bobot_server/butia/butia.htm
new file mode 100644
index 0000000..ca86673
--- /dev/null
+++ b/lib/support/bobot_server/butia/butia.htm
@@ -0,0 +1,17 @@
+<html>
+<HEAD>
+ <TITLE>Robot Butia</TITLE>
+</HEAD>
+<frameset rows="25%,50%,25%">
+
+ <frame src="header.htm" />
+ <frameset cols="25%,75%">
+ <frame src="command.htm" />
+ <frame src="view.htm" />
+ </frameset>
+<frame src="sensors.htm" />
+
+</frameset>
+
+</html>
+
diff --git a/lib/support/bobot_server/butia/butia_http.lua b/lib/support/bobot_server/butia/butia_http.lua
new file mode 100644
index 0000000..6a0b1ff
--- /dev/null
+++ b/lib/support/bobot_server/butia/butia_http.lua
@@ -0,0 +1,32 @@
+module(..., package.seeall);
+
+--local devices=devices
+local process = require("bobot-server-process").process
+local util = require("http-util")
+
+local parse_params = util.parse_params
+local load_template = util.load_file
+
+local butia_template=load_template('butia/butia.htm') or "Error loading template butia.htm"
+local header_template=load_template('butia/header.htm') or "Error loading template header.htm"
+
+function init (get_page)
+ get_page["/butia.htm"] = function (p)
+ local params=parse_params(p)
+ local rep = {
+ ['DATA1'] = params['campo'],
+ ['DATA2'] = tostring(params['unboton'])..', '..tostring(params['otroboton']),
+ }
+ local page=string.gsub(butia_template, '<!%-%-(%w+)%-%->', rep)
+ return "HTTP/1.1 200/OK\r\nContent-Type:text/html\r\nContent-Length: "..#page.."\r\n\r\n"..page
+ end
+
+ get_page["/header.htm"] = function (p)
+ local params=parse_params(p)
+ local rep = {
+ }
+ local page=string.gsub(header_template, '<!%-%-(%w+)%-%->', rep)
+ return "HTTP/1.1 200/OK\r\nContent-Type:text/html\r\nContent-Length: "..#page.."\r\n\r\n"..page
+ end
+
+end
diff --git a/lib/support/bobot_server/butia/command.htm b/lib/support/bobot_server/butia/command.htm
new file mode 100644
index 0000000..9cec722
--- /dev/null
+++ b/lib/support/bobot_server/butia/command.htm
@@ -0,0 +1,36 @@
+<HTML>
+
+<BODY BGCOLOR="#bfbfbf" TEXT="#000000" VLINK="#000099" LINK="#9900ff" ALINK="#FFFF00">
+<CENTER>
+<h1 style="color: rgb(0, 153, 0);">Haz click en los botones para dirigir el robot</h1>
+<hr>
+<BR>
+<TABLE BORDER=1 WIDTH="95%" CELLSPACING=3 CELLPADDING=3>
+<TR>
+ <TD ALIGN="center" VALIGN="top">
+ <TABLE BORDER=1 WIDTH="95%" CELLSPACING=3 CELLPADDING=3>
+ <TR>
+ <TD ALIGN="center"></TD>
+ <TD ALIGN="center"><A HREF="up.htm"><IMG SRC="images/btar_up.gif" BORDER=0 WIDTH=20 HEIGHT=20></A></TD>
+ <TD ALIGN="center"></TD>
+ </TR>
+ <TR>
+ <TD ALIGN="center"><A HREF="left.htm"><IMG SRC="images/btar_lft.gif" BORDER=0 WIDTH=20 HEIGHT=20></A></TD>
+ <TD ALIGN="center"></TD>
+ <TD ALIGN="center"><A HREF="right.htm"><IMG SRC="images/btar_rgt.gif" BORDER=0 WIDTH=20 HEIGHT=20></A></TD>
+ </TR>
+ <TR>
+ <TD ALIGN="center"></TD>
+ <TD ALIGN="center"><A HREF="down.htm"><IMG SRC="images/btar_dn.gif" BORDER=0 WIDTH=20 HEIGHT=20></A></TD>
+ <TD ALIGN="center"></TD>
+ </TR>
+ </TABLE>
+ </TD>
+</TR>
+</TABLE>
+<P>
+
+</CENTER>
+</BODY>
+</HTML>
+
diff --git a/lib/support/bobot_server/butia/describeButia.htm b/lib/support/bobot_server/butia/describeButia.htm
new file mode 100644
index 0000000..b147468
--- /dev/null
+++ b/lib/support/bobot_server/butia/describeButia.htm
@@ -0,0 +1,88 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<HTML>
+<HEAD>
+<TITLE>
+butia (Describe)
+</TITLE>
+</HEAD>
+
+<BODY BGCOLOR="white" >
+<HR>
+<TABLE BORDER="0" WIDTH="100%" CELLPADDING="1" CELLSPACING="0" SUMMARY="">
+<TR>
+<TD COLSPAN=2 BGCOLOR="#EEEEFF" >
+<A NAME="navbar_top_firstrow"><!-- --></A>
+<TABLE BORDER="0" CELLPADDING="0" CELLSPACING="3" SUMMARY="">
+ <TR ALIGN="center" VALIGN="top">
+ <TD BGCOLOR="#EEEEFF" > &nbsp;<FONT ><B>DESCRIBE butia</B></FONT>&nbsp;</TD>
+ <TD BGCOLOR="#EEEEFF" > <A HREF="lback.htm"><FONT><B>DESCRIBE lback</B></FONT></A>&nbsp;</TD>
+ <TD BGCOLOR="#FFFFFF" > <A HREF="dist.htm"><FONT ><B>DESCRIBE dist</B></FONT></A>&nbsp;</TD>
+
+ </TR>
+</TABLE>
+</TD>
+<TD ALIGN="right" VALIGN="top" ROWSPAN=3><EM>
+<b>Butia<br>Robot&nbsp;Educativo</b></EM>
+</TD>
+</TR>
+</TABLE>
+<HR>
+<H2>
+<FONT SIZE="-1">
+Funciones disponibles en </FONT>
+<BR>
+butia</H2>
+
+<HR>
+
+<P>
+A continuaci&oacute;n se lista las funciones disponibles en este m&oacute;dulo.
+<br>
+Puedes invocar la funci&oacute;n ingresando los datos necesarios y presionando el bot&oacute;n Submit.
+<p>
+
+<P>
+
+<A NAME="method_summary"><!-- --></A>
+<TABLE BORDER="1" WIDTH="100%" CELLPADDING="3" CELLSPACING="0" SUMMARY="">
+<TR BGCOLOR="#CCCCFF" >
+<TH ALIGN="left" COLSPAN="2"><FONT SIZE="+2">
+<B>Resumen de Funciones</B></FONT></TH>
+</TR>
+
+
+<TR BGCOLOR="white" >
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;data&nbsp;(String)</CODE></FONT></TD>
+<TD><CODE><B>read_ver</B>(data&nbsp;number)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+<FORM METHOD="POST" ACTION="evaluate_function.do">
+<HIDDEN VALUE="read_ver"/>
+data: <INPUT TYPE="text" NAME="data" />
+<INPUT TYPE="submit" VALUE="Submit" />
+</FORM>
+</TD>
+</TR>
+
+<TR BGCOLOR="white" >
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;data&nbsp;(String)</CODE></FONT></TD>
+<TD><CODE><B>get_volt</B>()</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+<FORM METHOD="POST" ACTION="evaluate_function.do">
+<HIDDEN VALUE="get_volt"/>
+<INPUT TYPE="submit" VALUE="Submit" />
+</FORM>
+</TD>
+</TR>
+
+</TABLE>
+&nbsp;
+<P>
+
+</BODY>
+</HTML> \ No newline at end of file
diff --git a/lib/support/bobot_server/butia/header.htm b/lib/support/bobot_server/butia/header.htm
new file mode 100644
index 0000000..7d64136
--- /dev/null
+++ b/lib/support/bobot_server/butia/header.htm
@@ -0,0 +1,10 @@
+<HTML>
+
+<BODY BGCOLOR="#bfbfbf" TEXT="#000000" VLINK="#000099" LINK="#9900ff" ALINK="#FFFF00">
+<CENTER>
+<H1>ROBOT BUTIA</H1>
+<IMG SRC="butia/images/butiaRobot3.png" style="width: 152px; height: 113px;" ALT="Butia" align="middle"><P>
+<HR SIZE=1 NOSHADE>
+</CENTER>
+</BODY>
+</HTML>
diff --git a/lib/support/bobot_server/butia/images/btar_dn.gif b/lib/support/bobot_server/butia/images/btar_dn.gif
new file mode 100644
index 0000000..7f6b4f3
--- /dev/null
+++ b/lib/support/bobot_server/butia/images/btar_dn.gif
Binary files differ
diff --git a/lib/support/bobot_server/butia/images/btar_lft.gif b/lib/support/bobot_server/butia/images/btar_lft.gif
new file mode 100644
index 0000000..e104fe4
--- /dev/null
+++ b/lib/support/bobot_server/butia/images/btar_lft.gif
Binary files differ
diff --git a/lib/support/bobot_server/butia/images/btar_rgt.gif b/lib/support/bobot_server/butia/images/btar_rgt.gif
new file mode 100644
index 0000000..4cc5ae0
--- /dev/null
+++ b/lib/support/bobot_server/butia/images/btar_rgt.gif
Binary files differ
diff --git a/lib/support/bobot_server/butia/images/btar_up.gif b/lib/support/bobot_server/butia/images/btar_up.gif
new file mode 100644
index 0000000..e3180df
--- /dev/null
+++ b/lib/support/bobot_server/butia/images/btar_up.gif
Binary files differ
diff --git a/lib/support/bobot_server/butia/images/butiaRobot3.png b/lib/support/bobot_server/butia/images/butiaRobot3.png
new file mode 100644
index 0000000..f7e74cf
--- /dev/null
+++ b/lib/support/bobot_server/butia/images/butiaRobot3.png
Binary files differ
diff --git a/lib/support/bobot_server/butia/images/clase07.jpg b/lib/support/bobot_server/butia/images/clase07.jpg
new file mode 100644
index 0000000..acc498f
--- /dev/null
+++ b/lib/support/bobot_server/butia/images/clase07.jpg
Binary files differ
diff --git a/lib/support/bobot_server/butia/sensors.htm b/lib/support/bobot_server/butia/sensors.htm
new file mode 100644
index 0000000..dca9244
--- /dev/null
+++ b/lib/support/bobot_server/butia/sensors.htm
@@ -0,0 +1,40 @@
+<HTML>
+
+<BODY >
+<CENTER>
+
+<table cellspacing="0" cellpadding="5" border="1" align="top">
+<tr>
+<th> Sensor Name
+</th><th> Type (A/D)
+</th><th> Value
+</th><th> Other
+</th></tr>
+<tr>
+<td> Temperature
+</td><td> D
+</td><td> 23
+</td><td> C
+</td></tr>
+<tr>
+<td> Pote
+</td><td> A
+</td><td> 100
+</td><td>
+</td></tr>
+<tr>
+<td> Gas
+</td><td> A
+</td><td> 15
+</td><td>
+</td></tr>
+<tr>
+<td> Button
+</td><td> D
+</td><td> 1
+</td><td> Pressed
+</td></tr>
+
+</CENTER>
+</BODY>
+</HTML> \ No newline at end of file
diff --git a/lib/support/bobot_server/butia/view.htm b/lib/support/bobot_server/butia/view.htm
new file mode 100644
index 0000000..0fda3dc
--- /dev/null
+++ b/lib/support/bobot_server/butia/view.htm
@@ -0,0 +1,10 @@
+<HTML>
+
+<BODY BGCOLOR="#bfbfbf" TEXT="#000000" VLINK="#000099" LINK="#9900ff" ALINK="#FFFF00">
+<CENTER>
+
+<IMG SRC="images/clase07.jpg" WIDTH=100% HEIGHT=100% ALT="Butia"><P>
+
+</CENTER>
+</BODY>
+</HTML> \ No newline at end of file
diff --git a/lib/support/bobot_server/dumptemplate.txt b/lib/support/bobot_server/dumptemplate.txt
new file mode 100644
index 0000000..b1c1dfa
--- /dev/null
+++ b/lib/support/bobot_server/dumptemplate.txt
@@ -0,0 +1,11 @@
+<html>
+<head><title>Bobot dump</title></head>
+<body>
+<h2>Bobot</h2>
+<a href="/index.htm">home</a> | modules
+<hr>
+Modules: <!--LIST--><br>
+
+<hr>
+</body>
+</html>
diff --git a/lib/support/bobot_server/dumptemplate_descr.txt b/lib/support/bobot_server/dumptemplate_descr.txt
new file mode 100644
index 0000000..e34df38
--- /dev/null
+++ b/lib/support/bobot_server/dumptemplate_descr.txt
@@ -0,0 +1,37 @@
+<html>
+<head><title>Bobot dump</title></head>
+<body>
+<h2>Bobot dump</h2>
+<a href="/index.htm">home</a> | dump
+<hr>
+Modules: <!--LIST--><br>
+
+<HR>
+<H2>
+<FONT SIZE="-1">
+Funciones disponibles en </FONT>
+<BR>
+<!--MODULENAME--></H2>
+
+<HR>
+
+<P>
+A continuaci&oacute;n se lista las funciones disponibles en este m&oacute;dulo.
+<br>
+Puedes invocar la funci&oacute;n ingresando los datos necesarios y presionando el bot&oacute;n Submit.
+<p>
+
+<P>
+
+<A NAME="method_summary"><!-- --></A>
+<TABLE BORDER="1" WIDTH="100%" CELLPADDING="3" CELLSPACING="0" SUMMARY="">
+<TR BGCOLOR="#CCCCFF" >
+<TH ALIGN="left" COLSPAN="2"><FONT SIZE="+2">
+<B>Resumen de Funciones</B></FONT></TH>
+</TR>
+
+
+<!--ROWS--><br>
+<hr>
+</body>
+</html>
diff --git a/lib/support/bobot_server/dumptemplate_descr_row.txt b/lib/support/bobot_server/dumptemplate_descr_row.txt
new file mode 100644
index 0000000..ade4736
--- /dev/null
+++ b/lib/support/bobot_server/dumptemplate_descr_row.txt
@@ -0,0 +1,20 @@
+<TR BGCOLOR="white" >
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>(<!--RETURNS-->)</CODE></FONT></TD>
+<TD><CODE><B><!--COMMAND--></B>(<!--PARAMETERS-->)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+<FORM METHOD="POST" ACTION="/dump.htm">
+<INPUT TYPE=HIDDEN NAME="command" VALUE="<!--COMMAND-->"/>
+<INPUT TYPE=HIDDEN NAME="dsel" VALUE="<!--MODULENAME-->"/>
+<!--FORMFIELDS-->
+<INPUT TYPE="submit" VALUE="Submit" />
+</FORM>
+
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+<!--RESULT-->
+
+</TD>
+</TR>
+
diff --git a/lib/support/bobot_server/favicon.ico b/lib/support/bobot_server/favicon.ico
new file mode 100644
index 0000000..3834805
--- /dev/null
+++ b/lib/support/bobot_server/favicon.ico
Binary files differ
diff --git a/lib/support/bobot_server/http-util.lua b/lib/support/bobot_server/http-util.lua
new file mode 100644
index 0000000..c8b9a6c
--- /dev/null
+++ b/lib/support/bobot_server/http-util.lua
@@ -0,0 +1,41 @@
+module(..., package.seeall);
+
+local bobot = require("bobot")
+
+local my_path = debug.getinfo(1, "S").source:match[[^@?(.*[\/])[^\/]-$]]
+
+--local devices=devices
+function load_file (filename)
+ local served, err = io.open(my_path..filename, "r")
+ if served then
+ return served:read("*all")
+ else
+ bobot.debugprint("Error opening", my_path..filename,":", err)
+ end
+end
+
+function parse_params(s)
+ local params={}
+ for k,v in string.gmatch(s, '([%w%%%_%-]+)=([%w%%%_%-]+)') do
+ bobot.debugprint('param', k, v)
+ params[k]=v
+ end
+ return params
+end
+
+local page404="<html><head><title>404 Not Found</title></head><body><h3>404 Not Found!</h3><hr><small>bobot</small></body></html>"
+local http404="HTTP/1.1 404 Not Found\r\nContent-Type:text/html\r\nContent-Length: "..#page404.."\r\n\r\n" .. page404
+page404=nil
+local function error_page()
+ return http404
+end
+
+function find_page (page)
+ local page=string.sub(page,2)
+ local file=load_file(page)
+ if file then
+ return function() return file end
+ else
+ return error_page
+ end
+end
diff --git a/lib/support/bobot_server/indextemplate.txt b/lib/support/bobot_server/indextemplate.txt
new file mode 100644
index 0000000..24b2245
--- /dev/null
+++ b/lib/support/bobot_server/indextemplate.txt
@@ -0,0 +1,16 @@
+<html>
+<head><title>Bobot</title></head>
+<body>
+<h2>Bobot</h2>
+home | <a href="/dump.htm">modules</a>
+<hr>
+
+<img src="/bobot.png" alt="bobot logo" width="200" height="200" />
+<p>
+<a href="http://www.fing.edu.uy/inco/grupos/mina/">Grupo MINA</a><br>
+In.Co., Facultad de Ingenier&iacute;a<br>
+Universidad de la Rep&uacute;blica<br>
+Uruguay</p>
+<hr>
+</body>
+</html>
diff --git a/lib/support/drivers/admin.lua b/lib/support/drivers/admin.lua
new file mode 100644
index 0000000..c3e3da9
--- /dev/null
+++ b/lib/support/drivers/admin.lua
@@ -0,0 +1,11 @@
+local device = _G
+local RESET = string.char(0xFF)
+
+api={}
+api.reset = {}
+api.reset.parameters = {}
+api.reset.returns = {}
+api.reset.call = function (data)
+ device:send(RESET)
+end
+
diff --git a/lib/support/drivers/ax.lua b/lib/support/drivers/ax.lua
new file mode 100644
index 0000000..d505511
--- /dev/null
+++ b/lib/support/drivers/ax.lua
@@ -0,0 +1,118 @@
+local device = _G
+local WRITE_INFO = 0x01
+local READ_INFO = 0x02
+local GET_RAW_POS = 0x03
+local char000 = string.char(0,0,0)
+local mode='wheel'
+
+--byte id,byte regstart, int value
+api={}
+api.write_info = {}
+api.write_info.parameters = {[1]={rname="id", rtype="number", min=0, max=255},[2]={rname="regstart", rtype="number", min=0, max=255},[3]={rname="value", rtype="number", min=0, max=65536}} ----byte id,byte regstart, int value
+api.write_info.returns = {[1]={rname="write_info_return", rtype="number"}} --one return
+api.write_info.call = function (id, regstart, value)
+ id, regstart, value = tonumber(id), tonumber(regstart), tonumber(value)
+ local write_info_payload = string.char(WRITE_INFO, id, regstart, math.floor(value / 256),value % 256)
+ device:send(write_info_payload)
+ local write_info_response = device:read(2) or char000
+ local raw_val = (string.byte(write_info_response, 2) or 0)
+ return raw_val
+end
+
+--- Set wheel mode.
+--Set the motor to continuous rotation mode.
+api.wheel_mode = {}
+api.wheel_mode.parameters = {[1]={rname="id", rtype="number", min=0, max=255}}
+api.wheel_mode.returns = {}
+api.wheel_mode.call = function (id )
+ id = tonumber(id)
+ local ret = device:send(string.char(WRITE_INFO,id,0x06,0x00,0x00))
+ local write_info_response = device:read(1) or string.char(0,0)
+ local ret = device:send(string.char(WRITE_INFO,id,0x08,0x00,0x00))
+ local write_info_response = device:read(1) or string.char(0,0)
+ mode='wheel'
+ end
+
+--- Set joint mode.
+-- Set the motor to joint mode. Angles are provided in degrees,
+-- in the full servo coverage (0 - 300 degrees arc)
+-- @param min the minimum joint angle (defaults to 0)
+-- @param max the maximum joint angle (defaults to 300)
+api.joint_mode = {}
+api.joint_mode.parameters = {[1]={rname="id", rtype="number", min=0, max=255},[2]={rname="minimo", rtype="number", min=0, max=1023},[3]={rname="maximo", rtype="number", min=0, max=1023}}
+api.joint_mode.returns = {}
+api.joint_mode.call = function (id ,minimo, maximo)
+ id = tonumber(id)
+ minimo=tonumber(minimo)
+ maximo=tonumber(maximo)
+ local ret = device:send(string.char(WRITE_INFO,id,0x06,math.floor(minimo / 256),minimo % 256))
+ local write_info_response = device:read(1) or string.char(0,0)
+ local ret = device:send(string.char(WRITE_INFO,id,0x08,math.floor(maximo / 256),maximo % 256))
+ local write_info_response = device:read(1) or string.char(0,0)
+ mode='joint'
+ end
+
+
+--- Set motor position.
+-- Set the target position for the motor's axle. Only works in
+-- joint mode.
+-- @param value Angle in degrees, in the 0 .. 300deg range.
+api.set_position = {}
+api.set_position.parameters = {[1]={rname="id", rtype="number", min=0, max=255},[2]={rname="pos", rtype="number", min=0, max=1023}}
+api.set_position.returns = {}
+api.set_position.call = function (id, pos )
+ id = tonumber(id)
+ pos = tonumber(pos)
+ local ret = device:send(string.char(WRITE_INFO,id,0x1E,math.floor(pos / 256),pos % 256))
+ local write_info_response = device:read(1) or string.char(0,0)
+ end
+
+
+--- Get motor position.
+-- Read the axle position from the motor.
+-- @return The angle in deg. The reading is only valid in the
+-- 0 .. 300deg range
+api.get_position = {}
+api.get_position.parameters = {[1]={rname="id", rtype="number", min=0, max=255},[2]={rname="pos", rtype="number", min=0, max=1023}}
+api.get_position.returns = {[1]={rname="motor_position", rtype="number"}} --one return
+api.get_position.call = function(id)
+ local send_response = device:send(string.char(GET_RAW_POS,id))
+ local value = device:read(3) or string.char(0,0,0)
+ local h_value = string.byte(value, 2)
+ local l_value = string.byte(value, 3)
+ local raw_angle = 256 * h_value + l_value
+ local ang=0.29*(raw_angle) -- deg ?
+ return raw_angle
+
+ end
+
+
+--- Set motor speed.
+-- @param value If motor in joint mode, speed in deg/sec in the 1 .. 684 range
+-- (0 means max available speed).
+-- If in wheel mode, as a fraction of max torque (in the -1 .. 1 range).
+api.set_speed = {}
+api.set_speed.parameters = {[1]={rname="id", rtype="number", min=0, max=255},[2]={rname="speed", rtype="number", min=-1, max=684}}
+api.set_speed.returns = {} --no return
+api.set_speed.call = function(id, speed)
+ --if mode=='joint' then
+ -- 0 .. 684 deg/sec
+ local vel=math.floor(speed * 1.496)
+ local lowb = math.floor(vel/ 256)
+ local highb = vel % 256
+
+
+ --local lowb, highb = get2bytes_unsigned(vel)
+ local ret = device:send(id,0x20,string.char(lowb,highb))
+ print ("ret= ",ret, " lowb= ", lowb, " highb= ", highb)
+ if ret then return ret:byte() end
+ --else --mode=='wheel'
+ -- -1 .. +1 max torque
+ --local vel=math.floor(speed * 1023)
+ --local lowb, highb = get2bytes_signed(vel)
+ --local ret = device:send(id,0x20,string.char(lowb,highb))
+ --if ret then return ret:byte() end
+ --end
+end
+
+
diff --git a/lib/support/drivers/boot.lua b/lib/support/drivers/boot.lua
new file mode 100644
index 0000000..2471ab9
--- /dev/null
+++ b/lib/support/drivers/boot.lua
@@ -0,0 +1,11 @@
+local device = _G
+local RESET = string.char(0xFF)
+
+api={}
+api.reset = {}
+api.reset.parameters = {} --no parameters
+api.reset.returns = {} --no returns
+api.reset.call = function ()
+ device:send(RESET)
+end
+
diff --git a/lib/support/drivers/boton.lua b/lib/support/drivers/boton.lua
new file mode 100644
index 0000000..4f846c9
--- /dev/null
+++ b/lib/support/drivers/boton.lua
@@ -0,0 +1,19 @@
+local device = _G
+
+local GET_VALUE=string.char(0x00)
+local string_byte=string.byte
+
+-- description: lets us know button's current status
+-- input: empty
+-- output: button's current status. Possible status: 1 pressed - 0 not pressed
+api={}
+api.getValue = {}
+api.getValue.parameters = {} -- no input parameters
+api.getValue.returns = {[1]={rname="state", rtype="int"}}
+api.getValue.call = function ()
+ device:send(GET_VALUE) -- operation code 1 = get button's status
+ local sen_dig_response = device:read(2) -- 2 bytes to read (opcode, data)
+ if not sen_dig_response or #sen_dig_response~=2 then return -1 end
+ local raw_val = string_byte(sen_dig_response, 2) or 0 -- keep data
+ return raw_val
+end
diff --git a/lib/support/drivers/butia.lua b/lib/support/drivers/butia.lua
new file mode 100644
index 0000000..b29c9f1
--- /dev/null
+++ b/lib/support/drivers/butia.lua
@@ -0,0 +1,39 @@
+local device = _G
+local RD_VERSION = string.char(0x02) -- lee la versión del firmware de la placa (Igual para 1.0 y 2.0)
+local GET_VOLT = string.char(0x03) -- obtiene el voltage de la batería (Igual para 1.0 y 2.0)
+
+api={}
+api.read_ver = {}
+api.read_ver.parameters = {}
+api.read_ver.returns = {[1]={rname="data", rtype="string"}}
+api.read_ver.call = function (data)
+ device:send(RD_VERSION)
+ local devolver = -1
+ local ret = device:read(2)
+ if ret then
+ devolver = string.byte(ret , 2) --leo el segundo byte obtenido que tiene la versión (el primero tiene el opcode)
+ end
+ --local devolver = (string.byte(version_response,2) or 0) + (string.byte(version_response,3) or 0)* 256
+ return devolver
+end
+
+api.get_volt = {}
+api.get_volt.parameters = {} -- no se envian parámetros
+api.get_volt.returns = {[1]={rname="volts", rtype="string"}} --nos devuelve el voltaje de las baterías
+api.get_volt.call = function ()
+ device:send(GET_VOLT) --envío el código de operación
+ local data_in = device:read(2) --leo 2 bytes, primero el código de operación y segundo el voltaje
+ local voltaje = string.byte(data_in or "00000000" , 2) --leo el segundo byte obtenido que es el que tiene el voltaje
+ --local resultado = string.char(math.floor(voltNum / 10),".",tonumber(volNum) % 256, " volts")
+ return voltaje
+end
+
+--[[
+function bytesToString(data)
+ local data_hex = ""
+ for i=1, string.len(data) do
+ data_hex = data_hex .. string.format('%02X', (string.byte(data, i)))
+ end
+ return data_hex
+end
+--]]
diff --git a/lib/support/drivers/buzzer.lua b/lib/support/drivers/buzzer.lua
new file mode 100644
index 0000000..a2ede05
--- /dev/null
+++ b/lib/support/drivers/buzzer.lua
@@ -0,0 +1,51 @@
+local device = _G
+local RD_VERSION = string.char(0x00)
+local PRENDER = string.char(0x01)
+local APAGAR = string.char(0x02)
+local BUZZER_CORTO = string.char(0x03)
+local BUZZER_TRIPLE = string.char(0x04)
+
+api={}
+api.read_version = {}
+api.read_version.parameters = {} --no parameters
+api.read_version.returns = {[1]={rname="version", rtype="number"}} --one return
+api.read_version.call = function ()
+ local get_read_version = RD_VERSION
+ device:send(get_read_version)
+ local version_response = device:read(2)
+ local raw_val = string.byte(version_response, 2)
+ --print("rawval, deg_temp: ", raw_val, deg_temp)
+ return raw_val
+end
+
+api.prender = {}
+api.prender.parameters = {} --no parameters
+api.prender.returns = {} --no return
+api.prender.call = function ()
+ local write_res, err = device:send(PRENDER)
+ if write_res then return 1 else return 0 end
+end
+
+api.apagar = {}
+api.apagar.parameters = {} --no parameters
+api.apagar.returns = {} --no return
+api.apagar.call = function ()
+ local write_res, err = device:send(APAGAR)
+ if write_res then return 1 else return 0 end
+end
+
+api.buzzer_corto = {}
+api.buzzer_corto.parameters = {[1]={rname="num", rtype="number"}}
+api.buzzer_corto.returns = {} --no return
+api.buzzer_corto.call = function (num)
+ local write_res, err = device:send(BUZZER_CORTO .. string.char(num))
+ if write_res then return 1 else return 0 end
+end
+
+api.buzzer_triple = {}
+api.buzzer_triple.parameters = {[1]={rname="tiempo1", rtype="number"}, [2]={rname="tiempo2", rtype="number"}, [3]={rname="tiempo3", rtype="number"}}
+api.buzzer_triple.returns = {} --no return
+api.buzzer_triple.call = function (tiempo1, tiempo2, tiempo3)
+ local write_res, err = device:send(BUZZER_TRIPLE .. string.char(tiempo1) .. string.char(tiempo2) .. string.char(tiempo3))
+ if write_res then return 1 else return 0 end
+end
diff --git a/lib/support/drivers/debug.lua b/lib/support/drivers/debug.lua
new file mode 100644
index 0000000..d8191ec
--- /dev/null
+++ b/lib/support/drivers/debug.lua
@@ -0,0 +1,39 @@
+local device = _G
+local RD_VERSION = string.char(0x00)
+local RD_DEBUG = string.char(0x01)
+local MESSAGE = string.char(0x02)
+
+
+api={}
+api.read_version = {}
+api.read_version.parameters = {} --no parameters
+api.read_version.returns = {[1]={rname="version", rtype="number"}} --one return
+api.read_version.call = function ()
+ local get_read_version = RD_VERSION
+ device:send(get_read_version)
+ local version_response = device:read(2)
+ local raw_val = string.byte(version_response, 2)
+ --print("rawval, deg_temp: ", raw_val, deg_temp)
+ --return raw_val
+ return version_response
+end
+
+api.rd_debug = {}
+api.rd_debug.parameters = {} --no parameters
+api.rd_debug.returns = {[1]={rname="data", rtype="string"}} --debug message
+api.rd_debug.call = function ()
+ local write_res, err = device:send(RD_DEBUG)
+ local len = 4
+ local ret = device:read(len) or ""
+ print("====",ret, string.len(ret))
+ return ret
+end
+
+api.message = {}
+api.message.parameters = {} --no parameters
+api.message.returns = {}
+api.message.call = function ()
+ local write_res, err = device:send(MESSAGE)
+ return write_res
+end
+
diff --git a/lib/support/drivers/display.lua b/lib/support/drivers/display.lua
new file mode 100644
index 0000000..3629cb9
--- /dev/null
+++ b/lib/support/drivers/display.lua
@@ -0,0 +1,99 @@
+local device = _G
+
+local string_char=string.char
+
+local RD_VERSION = string_char(0x00)
+local ESCRIBIR = string_char(0x01)
+local PRUEBA = string_char(0x02)
+local BORRAR = string_char(0x03)
+local INICIAR = string_char(0x04)
+local PRENDER_BKL = string_char(0x08)
+local APAGAR_BKL = string_char(0x09)
+local AGENDAR_MSG = string_char(0x0A)
+local SET_TICKS = string_char(0x0B)
+local ESPACIO = string_char(0x20)
+
+
+api={}
+api.read_version = {}
+api.read_version.parameters = {} --no parameters
+api.read_version.returns = {[1]={rname="version", rtype="number"}} --one return
+api.read_version.call = function ()
+ device:send(RD_VERSION)
+ local version_response = device:read(2)
+ local raw_val = string.byte(temperature_response, 2)
+ --print("rawval, deg_temp: ", raw_val, deg_temp)
+ return raw_val
+end
+
+api.escribir = {}
+api.escribir.parameters = {[1]={rname="message", rtype="string"}}
+api.escribir.returns = {}
+api.escribir.call = function (str)
+ local msg = ESCRIBIR .. str
+ device:send(msg)
+ --device:read()
+end
+
+api.prueba = {}
+api.prueba.parameters = {} --no parameters
+api.prueba.returns = {} --no return
+api.prueba.call = function ()
+ device:send(PRUEBA)
+end
+
+api.borrar = {}
+api.borrar.parameters = {} --no parameters
+api.borrar.returns = {} --no return
+api.borrar.call = function ()
+ device:send(BORRAR)
+end
+
+api.iniciar = {}
+api.iniciar.parameters = {} --no parameters
+api.iniciar.returns = {} --no return
+api.iniciar.call = function ()
+ device:send(INICIAR)
+end
+
+api.prender_bkl = {}
+api.prender_bkl.parameters = {} --no parameters
+api.prender_bkl.returns = {} --no return
+api.prender_bkl.call = function ()
+ device:send(PRENDER_BKL)
+end
+
+api.apagar_bkl = {}
+api.apagar_bkl.parameters = {} --no parameters
+api.apagar_bkl.returns = {} --no return
+api.apagar_bkl.call = function ()
+ device:send(APAGAR_BKL)
+end
+
+api.set_ticks = {}
+api.set_ticks.parameters = {[1]={rname="cantTicks", rtype="numeric"}} --how many timmers ticks have to pass before display agendar_msg screen
+api.set_ticks.returns = {} --no return
+api.set_ticks.call = function (ticks)
+ device:send(SET_TICKS .. string_char(ticks))
+end
+
+api.agendar_msg = {}
+api.agendar_msg.parameters = {
+ [1]={rname="message", rtype="string"}, -- first parameter is the message
+ [2]={rname="isCiclic", rtype="numeric"}, -- 1 in case of a ciclic message 0 elsewere
+ [3]={rname="isEnd", rtype="numeric"}} -- 1 in case of end of message, so previously calls to agendar_msg could be concatenated
+api.agendar_msg.returns = {[1]={rname="isFull", rtype="boolean"}} --If it is no more space in the event buffer returns true, false elsewere
+api.agendar_msg.call = function (str, isCiclic, isEnd)
+ device:send(AGENDAR_MSG .. string_char(32) .. string_char(isEnd) .. string_char(isCiclic) .. str)
+ print("despues del send")
+ local ret = device:read(3) or char0000 --el tercer byte recibido indica con un 1 si el buffer circuilar que se utiliza para mantener los mensajes esta lleno, 0 en caso controario
+ print("despues del read")
+ local error = (string.byte(ret,3) or 0)
+ print("despues de capturar el 3er byte")
+ if(error == 1) then
+ print "error, buffer lleno"
+ else
+ print "ok"
+ end
+ return error
+end
diff --git a/lib/support/drivers/dist.lua b/lib/support/drivers/dist.lua
new file mode 100644
index 0000000..5b8a247
--- /dev/null
+++ b/lib/support/drivers/dist.lua
@@ -0,0 +1,25 @@
+local device = _G
+
+local GET_VALUE=string.char(0x00)
+local string_byte=string.byte
+
+-- description: lets us know dist sensor's current value
+-- input: empty
+-- output: dist sensor's current value.
+api={}
+api.getValue = {}
+api.getValue.parameters = {} -- no input parameters
+api.getValue.returns = {[1]={rname="par1", rtype="int"}}
+api.getValue.call = function ()
+ device:send(GET_VALUE) -- operation code 1 = get distance of object
+ local sen_anl_response = device:read(3) -- operation code and data
+ if not sen_anl_response or #sen_anl_response~=3 then return -1 end
+ --local raw_val = (string_byte(sen_anl_response, 2) or 0) + (string_byte(sen_anl_response, 3) or 0)* 256
+ raw_val = string.byte(sen_anl_response, 2)* 256 + string.byte(sen_anl_response, 3)
+ raw_val = 1024 - raw_val
+ return raw_val
+end
+
+
+
+
diff --git a/lib/support/drivers/dynamix.lua b/lib/support/drivers/dynamix.lua
new file mode 100644
index 0000000..52ea4ba
--- /dev/null
+++ b/lib/support/drivers/dynamix.lua
@@ -0,0 +1,34 @@
+local device = _G
+local WRITE_INFO = 0x01
+local SEND_BUS = 0x01
+local READ_INFO = 0x02
+local GET_RAW_POS = 0x03
+local char000 = string.char(0,0,0)
+
+--byte id,byte regstart, int value
+api={}
+api.write_info = {}
+api.write_info.parameters = {[1]={rname="id", rtype="number", min=0, max=255},[2]={rname="regstart", rtype="number", min=0, max=255},[3]={rname="value", rtype="number", min=0, max=65536}} ----byte id,byte regstart, int value
+api.write_info.returns = {[1]={rname="write_info_return", rtype="number"}} --one return
+api.write_info.call = function (id, regstart, value)
+ id, regstart, value = tonumber(id), tonumber(regstart), tonumber(value)
+ local write_info_payload = string.char(WRITE_INFO, id, regstart, math.floor(value / 256),value % 256)
+ device:send(write_info_payload)
+ local write_info_response = device:read(2) or char000
+ local raw_val = (string.byte(write_info_response, 2) or 0)
+ return raw_val
+end
+
+api.pasarela = {}
+api.pasarela.parameters = {[1]={rname="packet", rtype="string", min=0, max=255}}
+api.pasarela.returns = {}
+api.pasarela.call = function (value)
+ local valueN = tonumber(value)
+ local checksum = 255 - ((0xfe + 0x04 + 0x03 + 0x19 +valueN)%256)
+ print (checksum)
+ local paquete = string.char(SEND_BUS, 0xff, 0xff,0xfe, 0x04, 0x03, 0x19, valueN, checksum)
+ device:send(paquete)
+end
+
+
+
diff --git a/lib/support/drivers/gas.lua b/lib/support/drivers/gas.lua
new file mode 100644
index 0000000..a056759
--- /dev/null
+++ b/lib/support/drivers/gas.lua
@@ -0,0 +1,20 @@
+local device = _G
+local RD_GAS = string.char(0x01)
+local char000 = string.char(0,0,0)
+
+api={}
+api.get_gas = {}
+api.get_gas.parameters = {} --no parameter
+api.get_gas.returns = {[1]={rname="gas level", rtype="number"}} --one return
+api.get_gas.call = function ()
+ local get_payload = RD_GAS
+ device:send(get_payload)
+ local response = device:read(3)
+ if not response then
+ print ('WARN: api.get_gas.call failure on device:read(3)')
+ response=char000
+ end
+ local raw_val = string.byte(response, 2) + 255*string.byte(response, 3)
+ return raw_val
+end
+
diff --git a/lib/support/drivers/grises.lua b/lib/support/drivers/grises.lua
new file mode 100644
index 0000000..a680266
--- /dev/null
+++ b/lib/support/drivers/grises.lua
@@ -0,0 +1,19 @@
+local device = _G
+
+local GET_VALUE=string.char(0x00)
+local string_byte=string.byte
+
+-- description: lets us know grey sensor's current value
+-- input: empty
+-- output: grey sensor's current value.
+api={}
+api.getValue = {}
+api.getValue.parameters = {} -- no input parameters
+api.getValue.returns = {[1]={rname="par1", rtype="int"}}
+api.getValue.call = function ()
+ device:send(GET_VALUE) -- operation code 1 = get grey level
+ local sen_anl_response = device:read(3) -- operation code and data
+ if not sen_anl_response or #sen_anl_response~=3 then return -1 end
+ local raw_val = math.floor(((string_byte(sen_anl_response, 2) or 0) + (string_byte(sen_anl_response, 3) or 0)* 256)/ 100)
+ return raw_val
+end
diff --git a/lib/support/drivers/hotplug/button.lua b/lib/support/drivers/hotplug/button.lua
new file mode 100644
index 0000000..9ddba48
--- /dev/null
+++ b/lib/support/drivers/hotplug/button.lua
@@ -0,0 +1,32 @@
+local device = _G
+
+local RD_VERSION=string.char(0x00)
+local GET_VALUE=string.char(0x01)
+local string_byte=string.byte
+
+-- description: lets us know button module's version
+api={}
+api.getVersion = {}
+api.getVersion.parameters = {} -- no input parameters
+api.getVersion.returns = {[1]={rname="version", rtype="int"}}
+api.getVersion.call = function ()
+ device:send(RD_VERSION) -- operation code 0 = get version
+ local version_response = device:read(3) -- 3 bytes to read (opcode, data)
+ if not version_response or #version_response~=3 then return -1 end
+ local raw_val = (string_byte(version_response,2) or 0) + (string_byte(version_response,3) or 0)* 256
+ return raw_val
+end
+
+-- description: lets us know button's current status
+-- input: empty
+-- output: button's current status. Possible status: 1 pressed - 0 not pressed
+api.getValue = {}
+api.getValue.parameters = {} -- no input parameters
+api.getValue.returns = {[1]={rname="state", rtype="int"}}
+api.getValue.call = function ()
+ device:send(GET_VALUE) -- operation code 1 = get button's status
+ local sen_dig_response = device:read(2) -- 2 bytes to read (opcode, data)
+ if not sen_dig_response or #sen_dig_response~=2 then return -1 end
+ local raw_val = string_byte(sen_dig_response, 2) or 0 -- keep data
+ return raw_val
+end
diff --git a/lib/support/drivers/hotplug/distanc.lua b/lib/support/drivers/hotplug/distanc.lua
new file mode 100644
index 0000000..2340796
--- /dev/null
+++ b/lib/support/drivers/hotplug/distanc.lua
@@ -0,0 +1,32 @@
+local device = _G
+
+local RD_VERSION=string.char(0x00)
+local GET_VALUE=string.char(0x01)
+local string_byte=string.byte
+
+-- description: lets us know dist module's version
+api={}
+api.getVersion = {}
+api.getVersion.parameters = {} -- no input parameters
+api.getVersion.returns = {[1]={rname="version", rtype="int"}}
+api.getVersion.call = function ()
+ device:send(RD_VERSION) -- operation code 0 = get version
+ local version_response = device:read(3) -- 3 bytes to read (opcode, data)
+ if not version_response or #version_response~=3 then return -1 end
+ local raw_val = (string_byte(version_response,2) or 0) + (string_byte(version_response,3) or 0)* 256
+ return raw_val
+end
+
+-- description: lets us know dist sensor's current value
+-- input: empty
+-- output: dist sensor's current value.
+api.getValue = {}
+api.getValue.parameters = {} -- no input parameters
+api.getValue.returns = {[1]={rname="par1", rtype="int"}}
+api.getValue.call = function ()
+ device:send(GET_VALUE) -- operation code 1 = get distance of object
+ local sen_anl_response = device:read(3) -- operation code and data
+ if not sen_anl_response or #sen_anl_response~=3 then return -1 end
+ local raw_val = (string_byte(sen_anl_response, 2) or 0) + (string_byte(sen_anl_response, 3) or 0)* 256
+ return raw_val
+end
diff --git a/lib/support/drivers/hotplug/gpio.lua b/lib/support/drivers/hotplug/gpio.lua
new file mode 100644
index 0000000..331efb3
--- /dev/null
+++ b/lib/support/drivers/hotplug/gpio.lua
@@ -0,0 +1,19 @@
+local device = _G
+
+local RD_VERSION=string.char(0x00)
+local string_byte=string.byte
+
+-- description: lets us know button module's version
+api={}
+api.getVersion = {}
+api.getVersion.parameters = {} -- no input parameters
+api.getVersion.returns = {[1]={rname="version", rtype="int"}}
+api.getVersion.call = function ()
+ device:send(RD_VERSION) -- operation code 0 = get version
+ local version_response = device:read(3) -- 3 bytes to read (opcode, data)
+ if not version_response or #version_response~=3 then return -1 end
+ local raw_val = (string_byte(version_response,2) or 0) + (string_byte(version_response,3) or 0)* 256
+ return raw_val
+end
+
+
diff --git a/lib/support/drivers/hotplug/grey.lua b/lib/support/drivers/hotplug/grey.lua
new file mode 100644
index 0000000..eb24f36
--- /dev/null
+++ b/lib/support/drivers/hotplug/grey.lua
@@ -0,0 +1,32 @@
+local device = _G
+
+local RD_VERSION=string.char(0x00)
+local GET_VALUE=string.char(0x01)
+local string_byte=string.byte
+
+-- description: lets us know grey module's version
+api={}
+api.getVersion = {}
+api.getVersion.parameters = {} -- no input parameters
+api.getVersion.returns = {[1]={rname="version", rtype="int"}}
+api.getVersion.call = function ()
+ device:send(RD_VERSION) -- operation code 0 = get version
+ local version_response = device:read(3) -- 3 bytes to read (opcode, data)
+ if not version_response or #version_response~=3 then return -1 end
+ local raw_val = (string_byte(version_response,2) or 0) + (string_byte(version_response,3) or 0)* 256
+ return raw_val
+end
+
+-- description: lets us know grey sensor's current value
+-- input: empty
+-- output: grey sensor's current value.
+api.getValue = {}
+api.getValue.parameters = {} -- no input parameters
+api.getValue.returns = {[1]={rname="par1", rtype="int"}}
+api.getValue.call = function ()
+ device:send(GET_VALUE) -- operation code 1 = get grey level
+ local sen_anl_response = device:read(3) -- operation code and data
+ if not sen_anl_response or #sen_anl_response~=3 then return -1 end
+ local raw_val = (string_byte(sen_anl_response, 2) or 0) + (string_byte(sen_anl_response, 3) or 0)* 256
+ return raw_val
+end
diff --git a/lib/support/drivers/hotplug/light.lua b/lib/support/drivers/hotplug/light.lua
new file mode 100644
index 0000000..ce953b2
--- /dev/null
+++ b/lib/support/drivers/hotplug/light.lua
@@ -0,0 +1,32 @@
+local device = _G
+
+local RD_VERSION=string.char(0x00)
+local GET_VALUE=string.char(0x01)
+local string_byte=string.byte
+
+-- description: lets us know light module's version
+api={}
+api.getVersion = {}
+api.getVersion.parameters = {} -- no input parameters
+api.getVersion.returns = {[1]={rname="version", rtype="int"}}
+api.getVersion.call = function ()
+ device:send(RD_VERSION) -- operation code 0 = get version
+ local version_response = device:read(3) -- 3 bytes to read (opcode, data)
+ if not version_response or #version_response~=3 then return -1 end
+ local raw_val = (string_byte(version_response,2) or 0) + (string_byte(version_response,3) or 0)* 256
+ return raw_val
+end
+
+-- description: lets us know light sensor's current value
+-- input: empty
+-- output: light sensor's current value.
+api.getValue = {}
+api.getValue.parameters = {} -- no input parameters
+api.getValue.returns = {[1]={rname="par1", rtype="int"}}
+api.getValue.call = function ()
+ device:send(GET_VALUE) -- operation code 1 = get light level
+ local sen_anl_response = device:read(3) -- operation code and data
+ if not sen_anl_response or #sen_anl_response~=3 then return -1 end
+ local raw_val = (string_byte(sen_anl_response, 2) or 0) + (string_byte(sen_anl_response, 3) or 0)* 256
+ return raw_val
+end
diff --git a/lib/support/drivers/hotplug/port.lua b/lib/support/drivers/hotplug/port.lua
new file mode 100644
index 0000000..331efb3
--- /dev/null
+++ b/lib/support/drivers/hotplug/port.lua
@@ -0,0 +1,19 @@
+local device = _G
+
+local RD_VERSION=string.char(0x00)
+local string_byte=string.byte
+
+-- description: lets us know button module's version
+api={}
+api.getVersion = {}
+api.getVersion.parameters = {} -- no input parameters
+api.getVersion.returns = {[1]={rname="version", rtype="int"}}
+api.getVersion.call = function ()
+ device:send(RD_VERSION) -- operation code 0 = get version
+ local version_response = device:read(3) -- 3 bytes to read (opcode, data)
+ if not version_response or #version_response~=3 then return -1 end
+ local raw_val = (string_byte(version_response,2) or 0) + (string_byte(version_response,3) or 0)* 256
+ return raw_val
+end
+
+
diff --git a/lib/support/drivers/hotplug/tilt.lua b/lib/support/drivers/hotplug/tilt.lua
new file mode 100644
index 0000000..1076479
--- /dev/null
+++ b/lib/support/drivers/hotplug/tilt.lua
@@ -0,0 +1,19 @@
+local device = _G
+
+api={}
+api.getTilt = {}
+api.getTilt.parameters = {} -- -- no input parameters
+api.getTilt.returns = {[1]={rname="par1", rtype="int"}}
+api.getTilt.call = function ()
+ device:send(string.char(0x00)) -- codigo de operacion 0
+ local sen_dig_response = device:read(3)
+ local raw_val
+ if not sen_dig_response or string.byte(sen_dig_response or "00000000", 2) == nil or string.byte(sen_dig_response or "00000000", 3) == nil
+ then
+ raw_val = "nil value"
+ else
+ raw_val = string.byte(sen_dig_response, 3) % 2
+ end
+ return raw_val
+
+end
diff --git a/lib/support/drivers/hotplug/vibra.lua b/lib/support/drivers/hotplug/vibra.lua
new file mode 100644
index 0000000..0c3d985
--- /dev/null
+++ b/lib/support/drivers/hotplug/vibra.lua
@@ -0,0 +1,19 @@
+local device = _G
+
+api={}
+api.getVibra = {}
+api.getVibra.parameters = {} -- -- no input parameters
+api.getVibra.returns = {[1]={rname="par1", rtype="int"}}
+api.getVibra.call = function ()
+ device:send(string.char(0x00)) -- codigo de operacion 0
+ local sen_dig_response = device:read(3)
+ local raw_val
+ if not sen_dig_response or string.byte(sen_dig_response or "00000000", 2) == nil or string.byte(sen_dig_response or "00000000", 3) == nil
+ then
+ raw_val = "nil value"
+ else
+ raw_val = string.byte(sen_dig_response, 3) % 2
+ end
+ return raw_val
+
+end
diff --git a/lib/support/drivers/lback.lua b/lib/support/drivers/lback.lua
new file mode 100644
index 0000000..9f903b1
--- /dev/null
+++ b/lib/support/drivers/lback.lua
@@ -0,0 +1,21 @@
+local device = _G
+
+api={}
+api.send = {}
+api.send.parameters = {[1]={rname="data", rtype="string"}}
+api.send.returns = {}
+api.send.call = function (data)
+ --print("####", data, string.len(data))
+ device:send(data)
+end
+
+api.read = {}
+api.read.parameters = {[1]={rname="len", rtype="int", default=64, min=0, max=255}}
+api.read.returns = {[1]={rname="data", rtype="string"}}
+api.read.call = function (len)
+ local len = len or 64
+ local ret = device:read(len)
+-- print("====",ret, string.len(ret))
+ return ret
+end
+
diff --git a/lib/support/drivers/led.lua b/lib/support/drivers/led.lua
new file mode 100644
index 0000000..1095d93
--- /dev/null
+++ b/lib/support/drivers/led.lua
@@ -0,0 +1,17 @@
+local device = _G
+
+local string_char=string.char
+
+api={}
+api.setLight = {}
+api.setLight.parameters = {[1]={rname="message", rtype="string"}}
+api.setLight.returns = {}
+api.setLight.call = function (intensidad)
+ intensidad=tonumber(intensidad)
+ if (not intensidad) or intensidad<0 then intensidad=0
+ elseif intensidad>255 then intensidad=255 end
+
+ local msg = string_char(0x00) .. string_char(math.floor(intensidad)) -- entre 0 y 255
+ device:send(msg)
+ local version_response = device:read()
+end
diff --git a/lib/support/drivers/ledA.lua b/lib/support/drivers/ledA.lua
new file mode 100644
index 0000000..f76b501
--- /dev/null
+++ b/lib/support/drivers/ledA.lua
@@ -0,0 +1,46 @@
+local device = _G
+local RD_VERSION = string.char(0x00)
+local PRENDER = string.char(0x01)
+local APAGAR = string.char(0x02)
+local BLINK = string.char(0x03)
+
+api={}
+api.read_version = {}
+api.read_version.parameters = {} --no parameters
+api.read_version.returns = {[1]={rname="version", rtype="number"}} --one return
+api.read_version.call = function ()
+ local get_read_version = RD_VERSION
+ device:send(get_read_version)
+ local version_response = device:read(2)
+ local raw_val = string.byte(version_response, 2)
+ --print("rawval, deg_temp: ", raw_val, deg_temp)
+ return raw_val
+end
+
+api.prender = {}
+api.prender.parameters = {} --no parameters
+api.prender.returns = {} --no return
+api.prender.call = function ()
+ device:send(PRENDER)
+-- local response = device:read(2)
+-- print("[",string.byte(response, 1),",", string.byte(response, 2),"]")
+-- print("-----------------------------------------------")
+-- if (string.byte(response, 1) ~= nil or string.byte(response, 2) ~= nil) then
+-- print("vino data")
+-- end
+end
+
+api.apagar = {}
+api.apagar.parameters = {} --no parameters
+api.apagar.returns = {} --no return
+api.apagar.call = function ()
+ device:send(APAGAR)
+end
+
+api.blink = {}
+api.blink.parameters = {[1]={rname="time", rtype="number"}, [2]={rname="blinks", rtype="number"}}
+api.blink.returns = {} --no return
+api.blink.call = function (time, blinks)
+ local msg = BLINK .. string.char(time) .. string.char(blinks)
+ device:send(msg)
+end
diff --git a/lib/support/drivers/ledR.lua b/lib/support/drivers/ledR.lua
new file mode 100644
index 0000000..1d3e726
--- /dev/null
+++ b/lib/support/drivers/ledR.lua
@@ -0,0 +1,31 @@
+local device = _G
+local RD_VERSION = string.char(0x00)
+local PRENDER = string.char(0x01)
+local APAGAR = string.char(0x02)
+
+api={}
+api.read_version = {}
+api.read_version.parameters = {} --no parameters
+api.read_version.returns = {[1]={rname="version", rtype="number"}} --one return
+api.read_version.call = function ()
+ local get_read_version = RD_VERSION
+ device:send(get_read_version)
+ local version_response = device:read(2)
+ local raw_val = string.byte(version_response, 2)
+ --print("rawval, deg_temp: ", raw_val, deg_temp)
+ return raw_val
+end
+
+api.prender = {}
+api.prender.parameters = {} --no parameters
+api.prender.returns = {} --no return
+api.prender.call = function ()
+ device:send(PRENDER)
+end
+
+api.apagar = {}
+api.apagar.parameters = {} --no parameters
+api.apagar.returns = {} --no return
+api.apagar.call = function ()
+ device:send(APAGAR)
+end
diff --git a/lib/support/drivers/ledV.lua b/lib/support/drivers/ledV.lua
new file mode 100644
index 0000000..1d3e726
--- /dev/null
+++ b/lib/support/drivers/ledV.lua
@@ -0,0 +1,31 @@
+local device = _G
+local RD_VERSION = string.char(0x00)
+local PRENDER = string.char(0x01)
+local APAGAR = string.char(0x02)
+
+api={}
+api.read_version = {}
+api.read_version.parameters = {} --no parameters
+api.read_version.returns = {[1]={rname="version", rtype="number"}} --one return
+api.read_version.call = function ()
+ local get_read_version = RD_VERSION
+ device:send(get_read_version)
+ local version_response = device:read(2)
+ local raw_val = string.byte(version_response, 2)
+ --print("rawval, deg_temp: ", raw_val, deg_temp)
+ return raw_val
+end
+
+api.prender = {}
+api.prender.parameters = {} --no parameters
+api.prender.returns = {} --no return
+api.prender.call = function ()
+ device:send(PRENDER)
+end
+
+api.apagar = {}
+api.apagar.parameters = {} --no parameters
+api.apagar.returns = {} --no return
+api.apagar.call = function ()
+ device:send(APAGAR)
+end
diff --git a/lib/support/drivers/leds.lua b/lib/support/drivers/leds.lua
new file mode 100644
index 0000000..7e55ce6
--- /dev/null
+++ b/lib/support/drivers/leds.lua
@@ -0,0 +1,43 @@
+local device = _G
+local RD_VERSION = string.char(0x00)
+local PRENDER = string.char(0x01)
+local APAGAR = string.char(0x02)
+local BLINK = string.char(0x03)
+
+api={}
+api.read_version = {}
+api.read_version.parameters = {} --no parameters
+api.read_version.returns = {[1]={rname="version", rtype="number"}} --one return
+api.read_version.call = function ()
+ local get_read_version = RD_VERSION
+ device:send(get_read_version)
+ local version_response = device:read(2)
+ local raw_val = string.byte(version_response, 2)
+ --print("rawval, deg_temp: ", raw_val, deg_temp)
+ return raw_val
+end
+
+api.prender = {}
+api.prender.parameters = {[1]={rname="numLed", rtype="number"}} --recibe the led number
+api.prender.returns = {} --no return
+api.prender.call = function (ledNumber)
+ local write_res, err = device:send(PRENDER .. string.char(ledNumber))
+ if write_res then return 1 else return 0 end
+end
+
+api.apagar = {}
+api.apagar.parameters = {[1]={rname="numLed", rtype="number"}} --recibe the led number
+api.apagar.returns = {} --no return
+api.apagar.call = function (ledNumber)
+ local write_res, err = device:send(APAGAR .. string.char(ledNumber))
+ if write_res then return 1 else return 0 end
+end
+
+api.blink = {}
+api.blink.parameters = {[1]={rname="time", rtype="number"}, [2]={rname="blinks", rtype="number"}, [3]={rname="numLed", rtype="number"}}
+api.blink.returns = {} --no return
+api.blink.call = function (time, blinks, ledNumber)
+ local msg = BLINK .. string.char(time) .. string.char(blinks) .. string.char(ledNumber)
+ local write_res, err = device:send(msg)
+ if write_res then return 1 else return 0 end
+end
diff --git a/lib/support/drivers/luz.lua b/lib/support/drivers/luz.lua
new file mode 100644
index 0000000..ed14e26
--- /dev/null
+++ b/lib/support/drivers/luz.lua
@@ -0,0 +1,21 @@
+local device = _G
+
+api={}
+api.getLuz = {}
+api.getLuz.parameters = {} -- -- no input parameters
+api.getLuz.returns = {[1]={rname="par1", rtype="int"}}
+api.getLuz.call = function ()
+ device:send(string.char(0x00)) -- codigo de operacion 0
+ local sen_anl_response = device:read(3)
+ local raw_val
+ if not sen_anl_response or string.byte(sen_anl_response or "00000000", 2) == nil or string.byte(sen_anl_response or "00000000", 3) == nil
+ then
+ raw_val = "nil value"
+ else
+ raw_val = string.byte(sen_anl_response, 2)* 256 + string.byte(sen_anl_response, 3)
+ raw_val = 1024 - raw_val
+
+ end
+ return raw_val
+
+end
diff --git a/lib/support/drivers/magnet.lua b/lib/support/drivers/magnet.lua
new file mode 100644
index 0000000..e70b69c
--- /dev/null
+++ b/lib/support/drivers/magnet.lua
@@ -0,0 +1,21 @@
+local device = _G
+
+-- descripción: permite conocer el estado el botón en un momento dado.
+-- entrada: no tiene.
+-- salida: estado del botón. Posibles estados: 1 presionado, 0 libre.
+api={}
+api.getCampo = {}
+api.getCampo.parameters = {} -- no tiene parámetros de entrada
+api.getCampo.returns = {[1]={rname="par1", rtype="int"}} -- 1 = presionado, 0 = libre
+api.getCampo.call = function ()
+ device:send(string.char(0x00)) -- codigo de operacion = 0
+ local sen_dig_response = device:read(3) -- leo 2 bytes (opcode, data)
+ local raw_val
+ if not sen_dig_response or string.byte(sen_dig_response or "00000000", 2) == nil or string.byte(sen_dig_response or "00000000", 3) == nil
+ then
+ raw_val = "nil value"
+ else
+ raw_val = 1 - (string.byte(sen_dig_response, 3) % 2)
+ end
+ return raw_val
+end
diff --git a/lib/support/drivers/motor.lua b/lib/support/drivers/motor.lua
new file mode 100644
index 0000000..c1a86d6
--- /dev/null
+++ b/lib/support/drivers/motor.lua
@@ -0,0 +1,42 @@
+local device = _G
+local SET_VEL_ADL = 0x00 -- código de op para mover el motor hacia adelante
+local SET_VEL_ATR = 0x01 -- código de op para mover el motor hacia atrás
+
+
+api={}
+api.setveladl = {}
+api.setveladl.parameters = {[1]={rname="id", rtype="int"}, [2]={rname="vel", rtype="int"}} --primer parametro id motor, segundo velocidad
+api.setveladl.returns = {[1]={rname="dato", rtype="int"}} --codigo de operación
+api.setveladl.call = function (id, vel)
+ local msg = string.char(SET_VEL_ADL,id, math.floor(vel / 256),vel % 256)
+ device:send(msg)
+ local ret = device:read(1)
+ local raw_val = string.byte(ret or " ", 1)
+ return raw_val
+end
+
+api.setvelatr = {}
+api.setvelatr.parameters = {[1]={rname="id", rtype="int"}, [2]={rname="vel", rtype="int"}} --primer parametro id motor, segundo velocidad
+api.setvelatr.returns = {[1]={rname="dato", rtype="int"}} --codigo de operación
+api.setvelatr.call = function (id, vel)
+ local msg = string.char(SET_VEL_ATR,id, math.floor(vel / 256),vel % 256)
+ device:send(msg)
+ local ret = device:read(1)
+ local raw_val = string.byte(ret or " ", 1)
+ return raw_val
+end
+
+
+api.setvelatr2 = {}
+api.setvelatr2.parameters = {[1]={rname="id", rtype="int"}, [2]={rname="vel", rtype="int"}} --primer parametro id motor, segundo velocidad
+api.setvelatr2.returns = {[1]={rname="dato", rtype="int"}} --codigo de operación
+api.setvelatr2.call = function (vel)
+ local msg = string.char(SET_VEL_ATR,0, math.floor(vel / 256),vel % 256)
+ device:send(msg)
+ local msg = string.char(SET_VEL_ATR,1, math.floor(vel / 256),vel % 256)
+ device:send(msg)
+ local ret = device:read(1)
+ local ret = device:read(1)
+ local raw_val = string.byte(ret or " ", 1)
+ return raw_val
+end
diff --git a/lib/support/drivers/motorTm.lua b/lib/support/drivers/motorTm.lua
new file mode 100644
index 0000000..9343855
--- /dev/null
+++ b/lib/support/drivers/motorTm.lua
@@ -0,0 +1,47 @@
+local device = _G
+
+api={}
+api.step = {}
+api.step.parameters = {[1]={rname="step", rtype="int", min=0, max=65536}}
+api.step.returns = {}
+api.step.call = function (freq)
+ local msg = string.char(0x02) .. string.char(math.floor(freq / 256)) .. string.char(freq % 256)
+ device:send(msg)
+ device:read(1)
+end
+
+api.steps = {}
+api.steps.parameters = {[1]={rname="number", rtype="int", min=0, max=65536}}
+api.steps.returns = {}
+api.steps.call = function (number)
+ local msg = string.char(0x03) .. string.char(math.floor(number / 256)) .. string.char(number % 256)
+ device:send(msg)
+ device:read(1)
+end
+
+api.phasetype = {}
+api.phasetype.parameters = {[1]={rname="phasetype", rtype="int", min=0, max=2}}
+api.phasetype.returns = {}
+api.phasetype.call = function (phasetype)
+ local msg = string.char(0x04) .. string.char(phasetype)
+ device:send(msg)
+end
+
+api.power_on = {}
+api.power_on.parameters = {[1]={rname="power_on", rtype="int", min=0, max=1}}
+api.power_on.returns = {}
+api.power_on.call = function (on)
+ local msg = string.char(0x06) .. string.char(on)
+ device:send(msg)
+end
+
+api.direction = {}
+api.direction.parameters = {[1]={rname="direction", rtype="int", min=-1, max=1}}
+api.direction.returns = {}
+api.direction.call = function (dir)
+ if dir==-1 then dir=2 end
+ local msg = string.char(0x07) .. string.char(dir+1)
+ device:send(msg)
+end
+
+
diff --git a/lib/support/drivers/motores.lua b/lib/support/drivers/motores.lua
new file mode 100644
index 0000000..45d2967
--- /dev/null
+++ b/lib/support/drivers/motores.lua
@@ -0,0 +1,48 @@
+local device = _G
+local SET_VEL_MTR = 0x00 -- código de op para mover un motor con vel y sentido
+local SET_VEL_2MTR = 0x01 -- código de op para mover dos motores con vel y sentido
+
+
+api={}
+api.setvelmtr = {}
+api.setvelmtr.parameters = {[1]={rname="id", rtype="int"},[2]={rname="sentido", rtype="int"},[3]={rname="vel", rtype="int"}} --parametros, id sentido vel
+api.setvelmtr.returns = {[1]={rname="dato", rtype="int"}} --codigo de operación
+api.setvelmtr.call = function (id, sentido, vel)
+ vel=tonumber(vel)
+ if vel>1023 then vel=1023 end
+ local msg = string.char(SET_VEL_MTR,id, sentido, math.floor(vel / 256),vel % 256)
+ device:send(msg)
+ local ret = device:read(1)
+ local raw_val = string.byte(ret or " ", 1)
+ return raw_val
+end
+
+api.setvel2mtr = {}
+api.setvel2mtr.parameters = {[1]={rname="sentido", rtype="int"},[2]={rname="vel", rtype="int"},[3]={rname="sentido", rtype="int"},[4]={rname="vel", rtype="int"}}
+api.setvel2mtr.returns = {[1]={rname="dato", rtype="int"}} --codigo de operación
+api.setvel2mtr.call = function (sentido1, vel1, sentido2, vel2)
+ vel1, vel2 = tonumber(vel1), tonumber(vel2)
+ if vel1>1023 then vel1=1023 end
+ if vel2>1023 then vel2=1023 end
+ local msg = string.char(SET_VEL_2MTR,sentido1, math.floor(vel1 / 256),vel1 % 256, sentido2, math.floor(vel2 / 256),vel2 % 256)
+ device:send(msg)
+ local ret = device:read(1)
+ local raw_val = string.byte(ret or " ", 1)
+ return raw_val
+end
+
+
+api.setvelatr2 = {}
+api.setvelatr2.parameters = {[1]={rname="id", rtype="int"}, [2]={rname="vel", rtype="int"}} --primer parametro id motor, segundo velocidad
+api.setvelatr2.returns = {[1]={rname="dato", rtype="int"}} --codigo de operación
+api.setvelatr2.call = function (vel)
+ local vdiv, vmod = math.floor(vel / 256),vel % 256
+ local msg = string.char(SET_VEL_ATR, 0, vdiv, vmod)
+ device:send(msg)
+ msg = string.char(SET_VEL_ATR, 1, vdiv, vmod)
+ device:send(msg)
+ local ret = device:read(1)
+ ret = device:read(1)
+ local raw_val = string.byte(ret or " ", 1)
+ return raw_val
+end
diff --git a/lib/support/drivers/motorin.lua b/lib/support/drivers/motorin.lua
new file mode 100644
index 0000000..042f3cc
--- /dev/null
+++ b/lib/support/drivers/motorin.lua
@@ -0,0 +1,28 @@
+local device = _G
+
+api={}
+api.speed = {}
+api.speed.parameters = {[1]={rname="freq", rtype="int", min=0, max=65536}}
+api.speed.returns = {}
+api.speed.call = function (freq)
+ local msg = string.char(0x02) .. string.char(math.floor(freq / 256)) .. string.char(freq % 256)
+ device:send(msg)
+ device:read(1)
+end
+
+api.steps = {}
+api.steps.parameters = {[1]={rname="number", rtype="int", min=0, max=65536}}
+api.steps.returns = {}
+api.steps.call = function (number)
+ local msg = string.char(0x03) .. string.char(math.floor(number / 256)) .. string.char(number % 256)
+ device:send(msg)
+ device:read(1)
+end
+
+api.on = {}
+api.on.parameters = {[1]={rname="direction", rtype="int", min=-1, max=1}}
+api.on.returns = {}
+api.on.call = function (dir)
+ local msg = string.char(0x01) .. string.char(dir+1)
+ device:send(msg)
+end
diff --git a/lib/support/drivers/motors.lua b/lib/support/drivers/motors.lua
new file mode 100644
index 0000000..a7c9a05
--- /dev/null
+++ b/lib/support/drivers/motors.lua
@@ -0,0 +1,70 @@
+local device = _G
+local RD_VERSION=string.char(0x00)
+local SET_VEL_2MTR=0x01 -- código de op para mover dos motores con vel y sentido
+local TEST_MOTORS=string.char(0x02)
+local SET_VEL_MTR = 0x01 -- código de op para mover un motor con vel y sentido
+
+api={}
+api.getVersion = {}
+api.getVersion.parameters = {} -- no input parameters
+api.getVersion.returns = {[1]={rname="version", rtype="int"}}
+api.getVersion.call = function ()
+ device:send(RD_VERSION) -- operation code 0 = get version
+ local version_response = device:read(3) -- 3 bytes to read (opcode, data)
+ if not version_response or #version_response~=3 then return -1 end
+ local raw_val = (string.byte(version_response,2) or 0) + (string.byte(version_response,3) or 0)* 256
+ return raw_val
+end
+
+api.setvelmtr = {} -- no impl en firmware
+api.setvelmtr.parameters = {[1]={rname="id", rtype="int"},[2]={rname="sentido", rtype="int"},[3]={rname="vel", rtype="int"}} --parametros, id sentido vel
+api.setvelmtr.returns = {[1]={rname="dato", rtype="int"}} --codigo de operación
+api.setvelmtr.call = function (id, sentido, vel)
+ vel=tonumber(vel)
+ if vel>1023 then vel=1023 end
+ local msg = string.char(SET_VEL_MTR,id, sentido, math.floor(vel / 256),vel % 256)
+ device:send(msg)
+ local ret = device:read(1)
+ local raw_val = string.byte(ret or " ", 1)
+ return raw_val
+end
+
+api.setvel2mtr = {}
+api.setvel2mtr.parameters = {[1]={rname="sentido", rtype="int"},[2]={rname="vel", rtype="int"},[3]={rname="sentido", rtype="int"},[4]={rname="vel", rtype="int"}}
+api.setvel2mtr.returns = {[1]={rname="dato", rtype="int"}} --codigo de operación
+api.setvel2mtr.call = function (sentido1, vel1, sentido2, vel2)
+ vel1, vel2 = tonumber(vel1), tonumber(vel2)
+ if vel1>1023 then vel1=1023 end
+ if vel2>1023 then vel2=1023 end
+ local msg = string.char(SET_VEL_2MTR,sentido1, math.floor(vel1 / 256),vel1 % 256, sentido2, math.floor(vel2 / 256),vel2 % 256)
+ device:send(msg)
+ local ret = device:read(1)
+ local raw_val = string.byte(ret or " ", 1)
+ return raw_val
+end
+
+api.setvelatr2 = {} -- no impl en firmware
+api.setvelatr2.parameters = {[1]={rname="id", rtype="int"}, [2]={rname="vel", rtype="int"}} --primer parametro id motor, segundo velocidad
+api.setvelatr2.returns = {[1]={rname="dato", rtype="int"}} --codigo de operación
+api.setvelatr2.call = function (vel)
+ local vdiv, vmod = math.floor(vel / 256),vel % 256
+ local msg = string.char(SET_VEL_ATR, 0, vdiv, vmod)
+ device:send(msg)
+ msg = string.char(SET_VEL_ATR, 1, vdiv, vmod)
+ device:send(msg)
+ local ret = device:read(1)
+ ret = device:read(1)
+ local raw_val = string.byte(ret or " ", 1)
+ return raw_val
+end
+
+api.testMotors = {}
+api.testMotors.parameters = {} -- no input parameters
+api.testMotors.returns = {[1]={rname="dato", rtype="int"}}
+api.testMotors.call = function ()
+ device:send(TEST_MOTORS) -- operation code 2 = test motors
+ local ret = device:read(1) -- 1 byte to read (opcode)
+ if not ret or #ret~=1 then return -1 end
+ local ret = string.byte(ret, 1)
+ return ret
+end
diff --git a/lib/support/drivers/move.lua b/lib/support/drivers/move.lua
new file mode 100644
index 0000000..7c361e3
--- /dev/null
+++ b/lib/support/drivers/move.lua
@@ -0,0 +1,16 @@
+local device = _G
+local GET_MOVE = string.char(0x01)
+local char000 = string.char(0,0,0)
+
+api={}
+api.get_move = {}
+api.get_move.parameters = {} --no parameter
+api.get_move.returns = {[1]={rname="digital_value", rtype="number"}} --one return
+api.get_move.call = function ()
+ local get_move_payload = GET_MOVE
+ device:send(get_move_payload)
+ local move_response = device:read(2) or char000
+ local raw_val = (string.byte(move_response, 2) or 0)
+ return raw_val
+end
+
diff --git a/lib/support/drivers/pnp.lua b/lib/support/drivers/pnp.lua
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/lib/support/drivers/pnp.lua
diff --git a/lib/support/drivers/pote.lua b/lib/support/drivers/pote.lua
new file mode 100644
index 0000000..fac23cf
--- /dev/null
+++ b/lib/support/drivers/pote.lua
@@ -0,0 +1,16 @@
+local device = _G
+local RD_POTE = string.char(0x01)
+local char000 = string.char(0,0,0)
+
+api={}
+api.get_pote = {}
+api.get_pote.parameters = {} --no parameter
+api.get_pote.returns = {[1]={rname="analog_value", rtype="number"}} --one return
+api.get_pote.call = function ()
+ local get_pote_payload = RD_POTE
+ device:send(get_pote_payload)
+ local pote_response = device:read(3) or char000
+ local raw_val = (string.byte(pote_response, 2) or 0) + 255*(string.byte(pote_response, 3) or 0)
+ return raw_val
+end
+
diff --git a/lib/support/drivers/puerta.lua b/lib/support/drivers/puerta.lua
new file mode 100644
index 0000000..1d3e726
--- /dev/null
+++ b/lib/support/drivers/puerta.lua
@@ -0,0 +1,31 @@
+local device = _G
+local RD_VERSION = string.char(0x00)
+local PRENDER = string.char(0x01)
+local APAGAR = string.char(0x02)
+
+api={}
+api.read_version = {}
+api.read_version.parameters = {} --no parameters
+api.read_version.returns = {[1]={rname="version", rtype="number"}} --one return
+api.read_version.call = function ()
+ local get_read_version = RD_VERSION
+ device:send(get_read_version)
+ local version_response = device:read(2)
+ local raw_val = string.byte(version_response, 2)
+ --print("rawval, deg_temp: ", raw_val, deg_temp)
+ return raw_val
+end
+
+api.prender = {}
+api.prender.parameters = {} --no parameters
+api.prender.returns = {} --no return
+api.prender.call = function ()
+ device:send(PRENDER)
+end
+
+api.apagar = {}
+api.apagar.parameters = {} --no parameters
+api.apagar.returns = {} --no return
+api.apagar.call = function ()
+ device:send(APAGAR)
+end
diff --git a/lib/support/drivers/sec.lua b/lib/support/drivers/sec.lua
new file mode 100644
index 0000000..e89646b
--- /dev/null
+++ b/lib/support/drivers/sec.lua
@@ -0,0 +1,87 @@
+local device = _G
+local RD_VERSION = string.char(0x00)
+local GET_SEC = string.char(0X01)
+local INTRUSION = string.char(0x02)
+local RESET_FLAG = string.char(0x03)
+local CONT_INT = string.char(0x04)
+local MESS = string.char(0x05)
+local RESET = string.char(0xFF)
+
+api={}
+api.read_version = {}
+api.read_version.parameters = {} --no parameters
+api.read_version.returns = {[1]={rname="version", rtype="number"}} --one return
+api.read_version.call = function ()
+ local get_read_version = RD_VERSION
+ device:send(get_read_version)
+ local version_response = device:read(4)
+ local raw_val = string.byte(version_response, 3)
+ --print("rawval, deg_temp: ", raw_val, deg_temp)
+ return raw_val
+end
+
+api.get_sec = {}
+api.get_sec.parameters = {} --no parameters
+--api.get_sec.returns = {[1]={rname="error", rtype="string"},[2]={rname="SecSensorValue_1", rtype="number"},[3]={rname="SecSensorValue_2", rtype="number"}}
+api.get_sec.returns = {[1]={rname="SecSensorValue_1", rtype="number"},[2]={rname="SecSensorValue_2", rtype="number"}}
+api.get_sec.call = function ()
+ local send_res, err
+ send_res, err = device:send(GET_SEC)
+ local ret = device:read(3)
+ local SecSensorValue_1 = (string.byte(ret,2) or 0)
+ local SecSensorValue_2 = (string.byte(ret,3) or 0)
+-- local SecSensorValue_1 = (string.byte(ret,2))
+-- local SecSensorValue_2 = (string.byte(ret,3))
+ if ((SecSensorValue_1 == 0) and (SecSensorValue_2 == 0)) then
+ alarma = "00"
+ elseif ((SecSensorValue_1 == 0) and (SecSensorValue_2 == 1)) then
+ alarma = "01"
+ elseif ((SecSensorValue_1 == 1) and (SecSensorValue_2 == 0)) then
+ alarma = "10"
+ else
+ alarma = "11"
+ end
+ return alarma
+ --if ret then return true, SecSensorValue_1, SecSensorValue_2 else return false end
+end
+
+api.intrusion = {}
+api.intrusion.parameters = {} --no parameters
+api.intrusion.returns = {[1]={rname="alarma", rtype="number"}} --one return
+api.intrusion.call = function ()
+ local intrusion = INTRUSION
+ device:send(intrusion)
+ local alarma = device:read(1)
+ if (alarma == string.char(0x00)) then
+ alarma = 0
+ else
+ alarma = 1
+ end
+ return alarma
+end
+
+api.reset_flag = {}
+api.reset_flag.parameters = {} --no parameters
+api.reset_flag.returns = {[1]={rname="borrado", rtype="number"}} --one return
+api.reset_flag.call = function ()
+ local reset_flag = RESET_FLAG
+ device:send(reset_flag)
+ local borrado = device:read(1)
+ if (borrado == string.char(0x00)) then
+ borrado = 0
+ else
+ borrado = 1
+ end
+
+ return borrado
+end
+
+api.cont_int = {}
+api.cont_int.parameters = {} --no parameters
+api.cont_int.returns = {[1]={rname="cantidad", rtype="number"}} --one return
+api.cont_int.call = function ()
+ local cont_int = CONT_INT
+ device:send(cont_int)
+ local cantidad = device:read(1)
+ return string.byte(cantidad)
+end
diff --git a/lib/support/drivers/sensor.lua b/lib/support/drivers/sensor.lua
new file mode 100644
index 0000000..d4df8d4
--- /dev/null
+++ b/lib/support/drivers/sensor.lua
@@ -0,0 +1,52 @@
+local device = _G
+local SEN_DIG = string.char(0x03) -- consulta un sensor digital
+local SEN_ANL = string.char(0x00) -- consulta un sensor analogico
+local SEN_ I2C = string.char(0x02) -- consulta un sensor i2c
+
+api={}
+api.senanl = {}
+api.senanl.parameters = {[1]={rname="idPin", rtype="int"}} -- -- el parámetro indica el pin que queremos leer de la arduino
+api.senanl.returns = {[1]={rname="par1", rtype="int"}} --{[1]={rname="par1", rtype="int"}, [2]={rname="par2", rtype="int"}} --two return
+api.senanl.call = function (idPin)
+ device:send(string.char(0x00, idPin)) -- codigo de operacion 0
+ local sen_anl_response = device:read(3)
+ local raw_val
+ if not sen_anl_response or string.byte(sen_anl_response or "00000000", 2) == nil or string.byte(sen_anl_response or "00000000", 3) == nil
+ then
+ raw_val = "nil value"
+ else
+ raw_val = string.byte(sen_anl_response or "00000000", 2)* 256 + string.byte(sen_anl_response or "00000000", 3)
+ end
+ --local raw_val2 = string.byte(set_anl_response or " ", 3)
+ return raw_val --string.char(raw_val ,raw_val2)
+end
+
+api.sendig = {}
+api.sendig.parameters = {[1]={rname="idPin", rtype="int"}} -- el parámetro indica el pin que queremos leer de la arduino
+api.sendig.returns = {[1]={rname="lecturaSensor", rtype="int"}}
+api.sendig.call = function (idPin)
+ device:send(string.char(0x01, idPin)) -- codigo de operacion 1
+ local sen_dig_response = device:read(3)
+ local raw_val
+ --if not sen_dig_response
+ --then
+ -- raw_val = "nil value"
+ --else
+ raw_val = string.byte(sen_dig_response or "0000", 2)* 256 + string.byte(sen_dig_response or "0000", 3) + 0
+ --end
+ return raw_val
+
+end
+
+
+--api.seni2c = {}
+--api.seni2c.parameters = {} -- no params
+--api.seni2c.returns = {[1]={rname="par1", rtype="int"}, [2]={rname="par2", rtype="int"}} --two return
+--api.seni2c.call = function ()
+-- local get_sen_i2c = SET_I2C
+-- device:send(get_sen_i2c)
+-- local sen_i2c_response = device:read(2)
+-- local raw_val = string.byte(set_i2c_response, 2)
+-- return raw_val
+--end
+
diff --git a/lib/support/drivers/stmtr.lua b/lib/support/drivers/stmtr.lua
new file mode 100644
index 0000000..9bd9b40
--- /dev/null
+++ b/lib/support/drivers/stmtr.lua
@@ -0,0 +1,46 @@
+local device = _G
+
+api={}
+api.rawspeed = {}
+api.rawspeed.parameters = {[1]={rname="speed1", rtype="int", min=-5, max=5}, [2]={rname="speed2", rtype="int", min=-5, max=5}}
+api.rawspeed.returns = {}
+api.rawspeed.call = function (speed1, speed2)
+ local msg = string.char(0x02,speed1,speed2)
+ device:send(msg)
+ device:read()
+end
+
+api.t0cfg = {}
+api.t0cfg.parameters = {[1]={rname="t0_low", rtype="int", min=0, max=255}, [2]={rname="t0_high", rtype="int", min=0, max=255}}
+api.t0cfg.returns = {}
+api.t0cfg.call = function (t0_low, t0_high)
+ local msg = string.char(0x01,t0_low,t0_high)
+ device:send(msg)
+ device:read()
+end
+
+api={}
+api.speed = {}
+api.speed.parameters = {[1]={rname="vel1", rtype="float", min=-127, max=127},
+ [2]={rname="vel2", rtype="float", min=-127, max=127}}
+api.speed.returns = {}
+api.speed.call = function (vel1, vel2)
+ vel1=tonumber(vel1)
+ vel2=tonumber(vel2)
+
+ local speed1, speed2
+ if vel1>=0 then
+ speed1=vel1
+ else
+ speed1=0xFF + vel1 + 1
+ end
+ if vel2>=0 then
+ speed2=vel2
+ else
+ speed2=0xFF + vel2 + 1
+ end
+
+ local msg = string.char(0x02,speed1,speed2)
+ device:send(msg)
+ device:read()
+end
diff --git a/lib/support/drivers/temp.lua b/lib/support/drivers/temp.lua
new file mode 100644
index 0000000..09ffe9f
--- /dev/null
+++ b/lib/support/drivers/temp.lua
@@ -0,0 +1,28 @@
+local device = _G
+
+api={}
+api.getTemp = {}
+api.getTemp.parameters = {} -- -- no input parameters
+api.getTemp.returns = {[1]={rname="par1", rtype="int"}}
+api.getTemp.call = function ()
+ device:send(string.char(0x00)) -- codigo de operacion 0
+ local sen_anl_response = device:read(3)
+ local raw_val
+ if not sen_anl_response or string.byte(sen_anl_response or "00000000", 2) == nil or string.byte(sen_anl_response or "00000000", 3) == nil
+ then
+ raw_val = "nil value"
+ else
+ raw_val = string.byte(sen_anl_response, 2)* 256 + string.byte(sen_anl_response, 3)
+
+ local aux = (raw_val * 500) / 1024 --- obtengo la temperatura en grados
+
+ if aux > 180 then
+ raw_val = (raw_val * 45) / 1024
+ else
+ raw_val = aux
+ end
+
+ end
+ return raw_val
+
+end
diff --git a/lib/support/drivers/temp_lubot.lua b/lib/support/drivers/temp_lubot.lua
new file mode 100644
index 0000000..dd22fc4
--- /dev/null
+++ b/lib/support/drivers/temp_lubot.lua
@@ -0,0 +1,20 @@
+local device = _G
+local RD_TEMP = string.char(0x34, 0x02)
+local char000 = string.char(0,0,0)
+
+
+api={}
+api.get_temperature = {}
+api.get_temperature.parameters = {} --no parameters
+api.get_temperature.returns = {[1]={rname="temperature", rtype="number"}} --one return
+api.get_temperature.call = function ()
+ local get_temp_payload = RD_TEMP
+ device:send(get_temp_payload)
+ local temperature_response = device:read(3) or char000
+ local raw_val = string.byte(temperature_response, 2) + (string.byte(temperature_response, 3) * 256)
+ local raw_temp = raw_val / 8
+ local deg_temp = raw_temp * 0.0625
+ --print("rawval, deg_temp: ", raw_val, deg_temp)
+ return deg_temp
+end
+
diff --git a/lib/support/lib/bobot_baseboard.lua b/lib/support/lib/bobot_baseboard.lua
new file mode 100644
index 0000000..757731a
--- /dev/null
+++ b/lib/support/lib/bobot_baseboard.lua
@@ -0,0 +1,393 @@
+#!/usr/bin/lua
+
+--module(..., package.seeall);
+
+local my_path = debug.getinfo(1, "S").source:match[[^@?(.*[\/])[^\/]-$]]
+
+local bobot_device = require("bobot_device")
+local bobot = require("bobot")
+
+local NULL_BYTE = string.char(0x00)
+local DEFAULT_PACKET_SIZE = 0x04
+local GET_USER_MODULES_SIZE_COMMAND = string.char(0x05)
+local GET_USER_MODULE_LINE_COMMAND = string.char(0x06)
+local GET_HANDLER_SIZE_COMMAND = string.char(0x0A)
+local GET_HANDLER_TYPE_COMMAND = string.char(0x0B)
+local GET_LINES_RESPONSE_PACKET_SIZE = 5
+local GET_LINE_RESPONSE_PACKET_SIZE = 12
+local GET_HANDLER_TYPE_PACKET_SIZE = 5
+local GET_HANDLER_RESPONSE_PACKET_SIZE = 5 --
+local ADMIN_HANDLER_SEND_COMMAND = string.char(0x00)
+local ADMIN_MODULE_IN_ENDPOINT = 0x01
+local ADMIN_MODULE_OUT_ENDPOINT = 0x81
+local GET_USER_MODULE_LINE_PACKET_SIZE = 0x05
+local CLOSEALL_BASE_BOARD_COMMAND = string.char(0x07)
+local CLOSEALL_BASE_BOARD_RESPONSE_PACKET_SIZE = 5
+local TIMEOUT = 250 --ms
+local MAX_RETRY = 5
+
+local BaseBoard = {}
+
+
+--executes s on the console and returns the output
+local function run_shell (s)
+ local f = io.popen(s) -- runs command
+ local l = f:read("*a") -- read output of command
+ f:close()
+ return l
+end
+
+openable = {}
+hotplug = {}
+
+local function parse_drivers()
+ local driver_files=run_shell("sh -c 'ls "..my_path.."../drivers/*.lua 2> /dev/null'")
+ for filename in driver_files:gmatch('drivers%/(%S+)%.lua') do
+ --print ("Driver openable", filename)
+ openable[filename] = true
+ end
+ driver_files=run_shell("sh -c 'ls "..my_path.."../drivers/hotplug/*.lua 2> /dev/null'")
+ for filename in driver_files:gmatch('drivers%/hotplug%/(%S+)%.lua') do
+ --print ("Driver hotplug", filename)
+ hotplug[filename] = true
+ end
+end
+parse_drivers()
+
+local function load_modules(bb)
+ local retry = 0
+ bb.modules = {}
+
+ local n_modules=bb:get_user_modules_size()
+ while n_modules == nil and retry < MAX_RETRY do
+ n_modules=bb:get_user_modules_size()
+ bobot.debugprint("u4b:the module list size returned a nil value, trying to recover...")
+ retry = retry+1
+ end
+ if not n_modules then return nil end
+ retry=0
+ bobot.debugprint ("Reading modules:", n_modules)
+ for i = 1, n_modules do
+ local modulename=bb:get_user_module_line(i)
+ while modulename == nil and retry < MAX_RETRY do
+ bobot.debugprint("u4b:the module returned a nil value, trying to recover...")
+ modulename=bb:get_handler_type(i)
+ retry = retry+1
+ end
+ if not modulename then return nil end
+ if openable[modulename] then
+ bb.modules[i]=modulename
+ local d = bobot_device:new({
+ module=modulename,
+ --name=module,
+ baseboard=bb,
+ hotplug=false,
+ in_endpoint=0x01, out_endpoint=0x01,
+ }) -- in_endpoint=0x01, out_endpoint=0x01})
+ bb.devices[d]=true
+ bb.devices[#bb.devices+1]=d
+
+ bb.modules[modulename]=d
+ elseif hotplug[modulename] then
+ bb.modules[i]=modulename
+ bb.modules[modulename]=true
+ bb.hotplug = true -- bb has a hotplug module
+ else
+ bobot.debugprint("Loading modules: missing driver for",modulename)
+ end
+ end
+ return true
+end
+
+local function load_module_handlers(bb)
+ local retry = 0
+
+ local n_module_handlers=bb:get_handler_size()
+ while n_module_handlers == nil and retry < MAX_RETRY do
+ n_module_handlers=bb:get_handler_size()
+ bobot.debugprint("u4b:the module handler list size returned a nil value, trying to recover...")
+ retry = retry+1
+ end
+ if (not n_module_handlers) or (n_module_handlers > 32) then return nil end
+ retry=0
+ bobot.debugprint ("Reading moduleshandlers:", n_module_handlers)
+ for i=1, n_module_handlers do
+ local t_handler = bb:get_handler_type(i)
+ while(t_handler == nil and retry < MAX_RETRY) do
+ bobot.debugprint("u4b:the module handler returned a nil value, trying to recover...")
+ t_handler = bb:get_handler_type(i)
+ retry = retry+1
+ end
+ if not t_handler then return nil end
+ if t_handler<255 then
+ local modulename=bb.modules[t_handler+1]
+ local moduledev=bb.modules[modulename]
+ if type(moduledev)=='table'
+ and not moduledev.handler then
+ moduledev.handler=i-1
+ elseif moduledev==true then
+ --name=name.."@"..(i-1)
+ local d = bobot_device:new({
+ handler=i-1,
+ module=modulename,
+ --name=name,
+ baseboard=bb,
+ hotplug=(hotplug[modulename]),
+ in_endpoint=0x01, out_endpoint=0x01,
+ }) -- in_endpoint=0x01, out_endpoint=0x01})
+ if d then
+ bb.devices[d]=true
+ bb.devices[#bb.devices+1]=d
+ end
+ else
+ bobot.debugprint ("No opened device!")
+ end
+ end
+ end
+ return true
+end
+
+
+function BaseBoard:refresh()
+ self.devices = {}
+
+ if not load_modules(self) then
+ return nil,"failure reading modules"
+ end
+
+ if not load_module_handlers(self) then
+ return nil,"failure reading module handlers"
+ end
+ return true
+end
+
+--Instantiates BaseBoard object.
+--Loads list of modules installed on baseboard
+function BaseBoard:new(bb)
+ --parameters sanity check
+ assert(type(bb)=="table")
+ assert(type(bb.comms)=="table")
+
+ --OO boilerplate
+ setmetatable(bb, self)
+ self.__index = self
+
+ bb:refresh()
+
+--bobot.debugprint ('----------------')
+ --bb:force_close_all()
+--bobot.debugprint ('================')
+ return bb
+end
+
+--Closes all modules opened on baseboard
+function BaseBoard:close()
+ --state sanity check
+ assert(type(self.devices)=="table")
+
+ for _,d in ipairs(self.devices) do
+ if type(d.handler)=="number" then
+ bobot.debugprint ("closing", d.name, d.handler)
+ d:close()
+ end
+ end
+
+ --TODO actually close the baseboard
+end
+
+--returns number of modules present on baseboard
+function BaseBoard:get_user_modules_size()
+ --state sanity check
+ assert(type(self.comms)=="table")
+
+ local comms=self.comms
+
+ -- In case of get_user_modules_size command is atended by admin module in handler 0 and send operation is 000
+
+ local handler_packet = ADMIN_HANDLER_SEND_COMMAND .. string.char(DEFAULT_PACKET_SIZE) .. NULL_BYTE
+ local admin_packet = GET_USER_MODULES_SIZE_COMMAND
+ local get_user_modules_size_packet = handler_packet .. admin_packet
+
+ local write_res = comms.send(ADMIN_MODULE_IN_ENDPOINT, get_user_modules_size_packet, TIMEOUT)
+ if write_res then
+ local data, err = comms.read(ADMIN_MODULE_OUT_ENDPOINT, GET_LINES_RESPONSE_PACKET_SIZE, TIMEOUT)
+ if not data then
+ bobot.debugprint("u4b:get_user_modules_size:comunication with I/O board read error", err)
+ return 0
+ else
+ local user_modules_size = string.byte(data, 5)
+ return user_modules_size
+ end
+ else
+ bobot.debugprint("u4b:get_user_modules_size:comunication with I/O board write error", write_res)
+ return 0
+ end
+end
+
+--returns thename of a given (by a 1-based index)module
+function BaseBoard:get_user_module_line(index)
+ --state & parameter sanity check
+ assert(type(index)=="number")
+ assert(index>0)
+ assert(type(self.comms)=="table")
+
+
+ local comms=self.comms
+
+ -- In case of get_user_module_line command is atended by admin module in handler 0 and send operation is 000
+ local get_user_module_line_packet_length = string.char(GET_USER_MODULE_LINE_PACKET_SIZE)
+ local handler_packet = ADMIN_HANDLER_SEND_COMMAND .. get_user_module_line_packet_length .. NULL_BYTE
+ local admin_packet = GET_USER_MODULE_LINE_COMMAND .. string.char(index-1)
+ local get_user_module_line_packet = handler_packet .. admin_packet
+
+ local write_res = comms.send(ADMIN_MODULE_IN_ENDPOINT, get_user_module_line_packet, TIMEOUT)
+ if write_res then
+ local data, err = comms.read(ADMIN_MODULE_OUT_ENDPOINT, GET_LINE_RESPONSE_PACKET_SIZE, TIMEOUT)
+ if not data then
+ bobot.debugprint("u4b:get_user_modules_line:comunication with I/O board read error", err)
+ return
+ end
+ --the name is between a header and a null
+ local end_mark = string.find(data, "\000", GET_USER_MODULE_LINE_PACKET_SIZE, true)
+ if not end_mark then
+ bobot.debugprint ("u4b:get_user_module_line:Error parsing module name")
+ return
+ end
+ local module_name = string.sub(data, GET_USER_MODULE_LINE_PACKET_SIZE, end_mark-1)
+ return module_name
+ else
+ bobot.debugprint("u4b:get_user_module_line:comunication with I/O board write error", write_res)
+ end
+end
+
+function BaseBoard:get_handler_size() ------ NEW LISTI ------
+ --state sanity check
+ assert(type(self.comms)=="table")
+
+ local comms=self.comms
+
+ local handler_packet = ADMIN_HANDLER_SEND_COMMAND .. string.char(DEFAULT_PACKET_SIZE) .. NULL_BYTE
+ local admin_packet = GET_HANDLER_SIZE_COMMAND
+ local get_handler_size_packet = handler_packet .. admin_packet
+
+ local write_res = comms.send(ADMIN_MODULE_IN_ENDPOINT, get_handler_size_packet, TIMEOUT)
+ if write_res then
+ local data, err = comms.read(ADMIN_MODULE_OUT_ENDPOINT, GET_HANDLER_RESPONSE_PACKET_SIZE, TIMEOUT)
+ if not data then
+ bobot.debugprint("u4b:get_handler_size:comunication with I/O board read error", err)
+ return 0
+ else
+ local handler_size = string.byte(data, 5)
+ return handler_size
+ end
+ else
+ bobot.debugprint("u4b:get_handler_type:comunication with I/O board write error", write_res)
+ end
+end
+function BaseBoard:get_handler_type(index) ------ NEW LISTI ------
+ --state & parameter sanity check
+ assert(type(index)=="number")
+ assert(index>0)
+ assert(type(self.comms)=="table")
+
+ local comms=self.comms
+
+ -- In case of get_handler_type command is atended by admin module in handler 0 and send operation is 000
+ local get_handler_type_packet_length = string.char(GET_HANDLER_TYPE_PACKET_SIZE) --GET_USER_MODULE_LINE_PACKET_SIZE
+ local handler_packet = ADMIN_HANDLER_SEND_COMMAND .. get_handler_type_packet_length .. NULL_BYTE
+ local admin_packet = GET_HANDLER_TYPE_COMMAND .. string.char(index-1)
+ local get_handler_type_packet = handler_packet .. admin_packet
+
+ local write_res = comms.send(ADMIN_MODULE_IN_ENDPOINT, get_handler_type_packet, TIMEOUT)
+ if write_res then
+ local data, err = comms.read(ADMIN_MODULE_OUT_ENDPOINT, GET_HANDLER_RESPONSE_PACKET_SIZE, TIMEOUT)
+ if not data then
+ bobot.debugprint("u4b:get_handler_type:comunication with I/O board read error", err)
+ return 0
+ else
+ local handler_type = string.byte(data, 5)
+ return handler_type
+ end
+ else
+ bobot.debugprint("u4b:get_handler_type:comunication with I/O board write error", write_res)
+ end
+end
+
+-- resets the baseboard, after this operation the baseboard will claim reenumeration to the operative system
+-- this function is deprecated by force_close_all
+function BaseBoard:close_all()
+ for _,d in ipairs(self.devices) do
+ --bobot.debugprint ("===", d.name,d.handler)
+ if d.handler then d:close() end
+ end
+end
+
+-- switch the baseboard to the bootloader program implementend as a usb4all command to the admin module
+function BaseBoard:switch_to_bootloader()
+ --state & parameter sanity check
+ assert(type(self.comms)=="table")
+
+ local comms=self.comms
+ -- In case of reset_base_board command is atended by admin module in handler 0 and send operation is 000
+ local handler_packet = ADMIN_HANDLER_SEND_COMMAND .. string.char(DEFAULT_PACKET_SIZE) .. NULL_BYTE
+ local admin_packet = string.char(0x09) --SWITCH_TO_BOOT_BASE_BOARD_COMMAND
+ local boot_base_board_packet = handler_packet .. admin_packet
+
+ local write_res = comms.send(ADMIN_MODULE_IN_ENDPOINT, boot_base_board_packet, TIMEOUT)
+ --from this moment the board is reseted, so there is nothing more to do
+end
+
+function BaseBoard:reset()
+ --state & parameter sanity check
+ assert(type(self.comms)=="table")
+
+ local comms=self.comms
+ -- In case of reset_base_board command is atended by admin module in handler 0 and send operation is 000
+ local handler_packet = ADMIN_HANDLER_SEND_COMMAND .. string.char(DEFAULT_PACKET_SIZE) .. NULL_BYTE
+ local admin_packet = string.char(0xFF) --RESET_BASE_BOARD_COMMAND
+ local reset_base_board_packet = handler_packet .. admin_packet
+
+ local write_res = comms.send(ADMIN_MODULE_IN_ENDPOINT, reset_base_board_packet, TIMEOUT)
+ if write_res then
+ -- no tego que leer respuesta porque se reseteo
+ --libusb.close(libusb_handler)
+ --self.libusb_handler=nil
+ --for d_name,d in pairs(self.devices) do
+ --bobot.debugprint ("===", d.name,d.handler)
+ -- d.handler=nil
+ --end
+ else
+ bobot.debugprint("u4b:reset:comunication with I/O board write error", write_res)
+ end
+end
+
+function BaseBoard:force_close_all()
+ --state & parameter sanity check
+ assert(type(self.comms)=="table")
+
+ local comms=self.comms
+ -- In case of reset_base_board command is atended by admin module in handler 0 and send operation is 000
+ local handler_packet = ADMIN_HANDLER_SEND_COMMAND .. string.char(DEFAULT_PACKET_SIZE) .. NULL_BYTE
+ local admin_packet = CLOSEALL_BASE_BOARD_COMMAND
+ local reset_base_board_packet = handler_packet .. admin_packet
+
+--bobot.debugprint ('%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%')
+ local write_res = comms.send(ADMIN_MODULE_IN_ENDPOINT, reset_base_board_packet, TIMEOUT)
+--bobot.debugprint ('%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%')
+ if write_res then
+ local data, err = comms.read(ADMIN_MODULE_OUT_ENDPOINT, CLOSEALL_BASE_BOARD_RESPONSE_PACKET_SIZE, TIMEOUT)
+ if err then
+ bobot.debugprint("u4b:force_close_all:comunication with I/O board read error",err)
+ else
+ --bobot.debugprint("u4b:force_close_all:libusb read",string.byte(data,1,string.len(data)))
+ end
+ for _,d in ipairs(self.devices) do
+ --bobot.debugprint ("===", d.name,d.handler)
+ d.handler=nil
+ end
+ else
+ bobot.debugprint("u4b:force_close_all:comunication with I/O board write error", write_res)
+ end
+end
+
+return BaseBoard
diff --git a/lib/support/lib/bobot_device.lua b/lib/support/lib/bobot_device.lua
new file mode 100644
index 0000000..b560255
--- /dev/null
+++ b/lib/support/lib/bobot_device.lua
@@ -0,0 +1,216 @@
+--module(..., package.seeall);
+
+local bobot = require("bobot")
+
+local string_char = string.char
+local string_len = string.len
+local string_byte = string.byte
+
+local OPEN_COMMAND = string_char(0x00)
+local CLOSE_COMMAND = string_char(0x01)
+local HEADER_PACKET_SIZE = 6
+local NULL_BYTE = string_char(0x00)
+local ADMIN_MODULE_IN_ENDPOINT = 0x01
+local ADMIN_MODULE_OUT_ENDPOINT = 0x81
+local ADMIN_HANDLER_SEND_COMMAND = string_char(0x00)
+local OPEN_RESPONSE_PACKET_SIZE = 5
+local CLOSE_RESPONSE_PACKET_SIZE = 2
+local TIMEOUT = 200 --ms
+
+local READ_HEADER_SIZE = 3
+
+local my_path = debug.getinfo(1, "S").source:match[[^@?(.*[\/])[^\/]-$]]
+
+local Device = {
+ --some usefull stuff for the drivers to use
+ string=string,
+ print=bobot.debugprint,
+ math=math,
+ tonumber=tonumber,
+ tostring=tostring
+}
+
+
+local drivers_cache = setmetatable({}, {__mode='kv'})
+local function load_driver(d)
+ local modulename=d.module
+ if drivers_cache[modulename] then return drivers_cache[modulename] end
+
+ local drivername=string.match(modulename, '^(.-)%d*$')
+ local f, err
+ if d.hotplug then
+ f, err = loadfile(my_path.."../drivers/hotplug/"..drivername..".lua")
+ else
+ f, err = loadfile(my_path.."../drivers/"..drivername..".lua")
+ end
+ drivers_cache[modulename] = f
+ return f, err
+end
+
+--Instantiates Device object.
+--Attempts to load api from driver
+function Device:new(d)
+ --parameters sanity check
+ assert(type(d)=="table")
+ --assert(type(d.name)=="string")
+ assert(type(d.module)=="string")
+ assert(type(d.baseboard)=="table")
+ assert(type(d.baseboard.comms)=="table")
+ assert(type(d.baseboard.comms.send)=="function")
+ assert(type(d.baseboard.comms.read)=="function")
+
+ --OO boilerplate
+ setmetatable(d, self)
+ self.__index = self
+
+ --store locally, save 2 indirections
+ d.comms_send = d.baseboard.comms.send
+ d.comms_read = d.baseboard.comms.read
+
+ --attempt to load api from driver
+ local f, err = load_driver(d)
+ if f then
+ d._G=d
+
+ setfenv(f, d) --the driver's environment is the device
+ local status, err=pcall(f)
+ if status then
+ bobot.debugprint("u4d:new:Success loading driver:", d.module)
+ else
+ bobot.debugprint("u4d:new:Error initializing driver:", tostring(err))
+ end
+ else
+ bobot.debugprint("u4d:new:Error loading driver:", err)
+ return nil
+ end
+
+ return d
+end
+
+--opens the device. must be done before sending / reading / etc.
+--receives endpoints, which can be ommited if they were provided at Device creation
+function Device:open(in_endpoint, out_endpoint)
+ --state & parameter sanity check
+ assert(self.handler==nil)
+ --assert(type(self.name)=="string")
+ assert(type(in_endpoint)=="number" or type(self.in_endpoint)=="number")
+ assert(type(self.comms_send)=="function")
+ assert(type(self.comms_read)=="function")
+ assert(type(out_endpoint)=="number" or type(self.out_endpoint)=="number")
+
+ --save for later use
+ if in_endpoint then self.in_endpoint = in_endpoint end
+ if out_endpoint then self.out_endpoint = out_endpoint end
+
+ local module_name=self.module .."\000" -- usb4all expect null terminated names
+
+ local open_packet_length = string_char(HEADER_PACKET_SIZE + string_len(module_name))
+
+ local module_in_endpoint = string_char(self.in_endpoint)
+ local module_out_endpoint = string_char(self.out_endpoint)
+
+ local handler_packet = ADMIN_HANDLER_SEND_COMMAND .. open_packet_length .. NULL_BYTE
+ local admin_packet = OPEN_COMMAND .. module_in_endpoint .. module_out_endpoint .. module_name
+ local open_packet = handler_packet .. admin_packet
+ local write_res = self.comms_send(ADMIN_MODULE_IN_ENDPOINT, open_packet, TIMEOUT)
+
+ if not write_res then
+ bobot.debugprint("u4d:open:comunication with I/O board write error", write_res)
+ return false
+ end
+
+ local data, err = self.comms_read(ADMIN_MODULE_OUT_ENDPOINT, OPEN_RESPONSE_PACKET_SIZE, TIMEOUT)
+ if not data then
+ bobot.debugprint ("u4d:open:comunication with I/O boardread error", err)
+ return false
+ end
+
+ local handler = string_byte(data, 5)
+ --hander -1 meand error
+ if handler==255 then
+ bobot.debugprint ("u4d:open:Already open!",self.module,self.handler)
+ return
+ else
+ bobot.debugprint ("u4d:open:Success!",self.module,handler)
+ self.handler = handler --self.handler set means device is open
+ return true
+ end
+
+end
+
+--closes the device
+function Device:close()
+ if not self.handler then return end --already closed
+
+ --state sanity check
+ assert(type(self.handler)=="number")
+ assert(type(self.comms_send)=="function")
+ assert(type(self.comms_read)=="function")
+
+ local close_packet_length = string_char(0x04) --string.char(HEADER_PACKET_SIZE + string.len(module_name))
+ local handler_packet = ADMIN_HANDLER_SEND_COMMAND .. close_packet_length .. NULL_BYTE
+ local admin_packet = CLOSE_COMMAND .. string_char(self.handler)
+ local close_packet = handler_packet .. admin_packet
+
+ local write_res = self.comms_send(ADMIN_MODULE_IN_ENDPOINT, close_packet, TIMEOUT)
+ if not write_res then
+ bobot.debugprint("u4d:close:comunication with I/O board write error", write_res)
+ return
+ end
+ local data, err = self.comms_read(ADMIN_MODULE_OUT_ENDPOINT, CLOSE_RESPONSE_PACKET_SIZE, TIMEOUT)
+
+ self.handler = nil
+end
+
+--sends data (a string) to device
+function Device:send(data)
+ --state & parameter sanity check
+ data=tostring(data)
+ assert(type(data)=="string")
+ assert(type(self.handler)=="number")
+ assert(type(self.in_endpoint)=="number")
+ assert(type(self.comms_send)=="function")
+ assert(type(self.comms_read)=="function")
+
+ local len=string_len(data)
+
+ local shifted_handler = self.handler * 8
+ assert(shifted_handler<256, "u4d:send:shifted_handler vale " .. shifted_handler .. " excede el tamaño maximo representable en un byte (255)")
+ local user_module_handler_send_command = string_char(shifted_handler)
+ local send_packet_length = string_char(0x03 + len)
+ local send_packet = user_module_handler_send_command .. send_packet_length .. NULL_BYTE .. data
+
+ --local tini=socket.gettime()
+ local write_res, err = self.comms_send(self.in_endpoint, send_packet, TIMEOUT)
+ --bobot.debugprint ('%%%%%%%%%%%%%%%% device send',socket.gettime()-tini)
+
+ if not write_res then
+ bobot.debugprint("u4d:send:comunication with I/O board write error", err)
+ end
+
+ return write_res, err
+end
+
+--read data (len bytes max) from device
+function Device:read(len)
+ len = len or 255
+ --state & parameter sanity check
+ assert(type(len)=="number")
+ assert(type(self.handler)=="number")
+ assert(type(self.out_endpoint)=="number")
+ assert(type(self.comms_send)=="function")
+ assert(type(self.comms_read)=="function")
+
+ local data, err = self.comms_read(self.out_endpoint, len+READ_HEADER_SIZE, TIMEOUT)
+ if not data then
+ bobot.debugprint("u4d:read:comunication with I/O board read error", err)
+ return nil, err
+ end
+
+ local data_h = string.sub(data, READ_HEADER_SIZE+1, -1) --discard header
+
+ return data_h, err
+end
+
+return Device
+
diff --git a/lib/support/lib/comms_chotox.lua b/lib/support/lib/comms_chotox.lua
new file mode 100644
index 0000000..18e02bf
--- /dev/null
+++ b/lib/support/lib/comms_chotox.lua
@@ -0,0 +1,39 @@
+local bobot_device = require("bobot_device")
+
+local comms_chotox = {}
+
+function comms_chotox.send(endpoint, data, timeout)
+end
+
+function comms_chotox.read(endpoint, len, timeout)
+end
+
+
+function comms_chotox.init(baseboards)
+ --parameters sanity check
+ assert(type(baseboards)=="table")
+
+ local n_boards=1
+ --local bb = bobot_baseboard.BaseBoard:new({idBoard=iSerial, comms=comms_usb})
+ local bb = {idBoard=1, comms=comms_chotox}
+ local devices={}
+ local is_hotplug= {button=true, led=true, grey=true, distanc=true}
+ for i, name in ipairs({"button", "grey", "distanc","butia"}) do
+ local dd={name=name, module=name, baseboard=bb, handler=i}
+ dd.open = function() return true end
+ dd.close = function() end
+ dd.read = function() return "" end
+ dd.send = function() return true end
+ if is_hotplug[name] then dd.hotplug=true end
+
+ local d = bobot_device:new(dd) -- in_endpoint=0x01, out_endpoint=0x01})
+
+ devices[name]=true
+ devices[#devices+1]=d
+ end
+ bb.devices=devices
+ baseboards[1]=bb
+ return n_boards
+end
+
+return comms_chotox
diff --git a/lib/support/lib/comms_serial.lua b/lib/support/lib/comms_serial.lua
new file mode 100644
index 0000000..4bd3bb0
--- /dev/null
+++ b/lib/support/lib/comms_serial.lua
@@ -0,0 +1,94 @@
+--module(..., package.seeall);
+
+--local socket=require("socket")
+
+local bobot_baseboard = require("bobot_baseboard")
+local bobot = require("bobot")
+
+local my_path = debug.getinfo(1, "S").source:match[[^@?(.*[\/])[^\/]-$]]
+assert(package.loadlib(my_path .. "lua_serialcomm.so","luaopen_serialcomm"))()
+local serialcomm=_G.serialcomm; _G.serialcomm=nil
+
+local serial_handler
+
+--executes s on the console and returns the output
+local function run_shell (s)
+ local f = io.popen(s) -- runs command
+ local l = f:read("*a") -- read output of command
+ f:close()
+ return l
+end
+
+local function split_words(s)
+ local words={}
+ for p in string.gmatch(s, "%S+") do
+ words[#words+1]=p
+ end
+ return words
+end
+
+local comms_serial = {}
+
+function comms_serial.send(endpoint, data, timeout)
+ --parameters sanity check
+ assert(type(serial_handler)=="number")
+ --assert(type(endpoint)=="number")
+ assert(type(data)=="string")
+ assert(type(timeout)=="number")
+
+ --local tini=socket.gettime()
+ local ret = serialcomm.send_msg(serial_handler, data)
+ --bobot.debugprint ('%%%%%%%%%%%%%%%% comms serial send',socket.gettime()-tini)
+ return ret
+end
+
+function comms_serial.read(endpoint, len, timeout)
+ --parameters sanity check
+ assert(type(serial_handler)=="number")
+ --assert(type(endpoint)=="number")
+ --assert(type(len)=="number")
+ --assert(type(timeout)=="number")
+
+ return serialcomm.read_msg(serial_handler, len, timeout)
+end
+
+
+function comms_serial.init(baseboards)
+ --parameters sanity check
+ assert(type(baseboards)=="table")
+
+ --FIXME leer ttyusbs...
+ --local tty_s=run_shell("ls /dev/ttyUSB* ")
+ local tty_s=run_shell("sh -c 'ls /dev/ttyUSB* 2> /dev/null'") --supress errors
+ local tty_t=split_words(tty_s)
+ local tty
+ local err
+ if (#tty_t == 0) then
+ return 0,"no ttyUSB found"
+ end
+
+ -- tty="/dev/ttyUSB0"
+ --for i=1, #tty_t do
+ for _, ttyI in ipairs(tty_t) do
+ bobot.debugprint ("Trying to connect to", ttyI)
+ serial_handler, err = serialcomm.init(ttyI, 115200)
+ if serial_handler then
+ tty=ttyI
+ break
+ else
+ bobot.debugprint("Error connecting:", err)
+ end
+ end
+ if not serial_handler then
+ bobot.debugprint("cs:", "no ttyUSB could be open")
+ return 0, err
+ end
+ bobot.debugprint ("cs:", tty)
+ local bb = bobot_baseboard:new({idBoard=tty, comms=comms_serial})
+
+ baseboards[#baseboards+1]=bb
+
+ return 1
+end
+
+return comms_serial
diff --git a/lib/support/lib/comms_usb.lua b/lib/support/lib/comms_usb.lua
new file mode 100644
index 0000000..91d64b5
--- /dev/null
+++ b/lib/support/lib/comms_usb.lua
@@ -0,0 +1,99 @@
+--module(..., package.seeall);
+
+local bobot_baseboard = require("bobot_baseboard")
+local bobot = require("bobot")
+
+local my_path = debug.getinfo(1, "S").source:match[[^@?(.*[\/])[^\/]-$]]
+assert(package.loadlib(my_path .. "libluausb.so","luaopen_libusb"))()
+local libusb=_G.libusb; _G.libusb=nil
+
+local usb_bulk_write = libusb.bulk_write
+local usb_bulk_read = libusb.bulk_read
+
+local USB4ALL_VENDOR = 0x04d8
+local USB4ALL_PRODUCT = 0x000c
+local USB4ALL_CONFIGURATION = 1
+local USB4ALL_INTERFACE = 0
+
+local READ_HEADER_SIZE = 3
+
+local libusb_handler
+
+
+local comms_usb = {}
+
+function comms_usb.send(endpoint, data, timeout)
+ --parameters sanity check
+ assert(type(libusb_handler)=="userdata")
+ assert(type(endpoint)=="number")
+ assert(type(data)=="string")
+ assert(type(timeout)=="number")
+
+ return usb_bulk_write(libusb_handler, endpoint, data, timeout)
+end
+
+function comms_usb.read(endpoint, len, timeout)
+ --parameters sanity check
+ assert(type(libusb_handler)=="userdata")
+ assert(type(endpoint)=="number")
+ assert(type(len)=="number")
+ assert(type(timeout)=="number")
+
+ return usb_bulk_read(libusb_handler, endpoint, len+READ_HEADER_SIZE, timeout)
+end
+
+
+function comms_usb.init(baseboards)
+ --parameters sanity check
+ assert(type(baseboards)=="table")
+
+
+ --refresh devices and buses
+ libusb.find_busses()
+ libusb.find_devices()
+ local n_boards = 0
+
+ local buses=libusb.get_busses()
+ for dirname, bus in pairs(buses) do --iterate buses
+ local devices=libusb.get_devices(bus)
+ for filename, device in pairs(devices) do --iterate devices
+ local descriptor = libusb.device_descriptor(device)
+
+ --if device is baseboard...
+ if ((descriptor.idVendor == USB4ALL_VENDOR) and (descriptor.idProduct == USB4ALL_PRODUCT)) then
+ --try to intialize baseboard
+ bobot.debugprint("Initializing Baseboard:", descriptor.idVendor, descriptor.idProduct)
+ libusb_handler = libusb.open(device)
+
+ if not libusb_handler then
+ bobot.debugprint("Error opening device")
+ break
+ end
+ if not libusb.set_configuration(libusb_handler, USB4ALL_CONFIGURATION) then
+ bobot.debugprint("Error configuring device, retrying after a reset")
+ libusb.reset(libusb_handler)
+ if not libusb.set_configuration(libusb_handler, USB4ALL_CONFIGURATION) then
+ bobot.debugprint("Error configuring device.")
+ break
+ end
+ end
+ if not libusb.claim_interface(libusb_handler, USB4ALL_INTERFACE) then
+ bobot.debugprint("Error seting device interface")
+ break
+ end
+
+ --success initializing, instantiate BaseBoard object and register
+ local iSerial=descriptor.iSerialNumber
+ local bb = bobot_baseboard:new({idBoard=iSerial, comms=comms_usb})
+ --bb:force_close_all()
+ --bobot.debugprint("Baseboard:", iSerial)
+
+ baseboards[#baseboards+1]=bb
+ n_boards = n_boards + 1
+ end
+ end
+ end
+ return n_boards
+end
+
+return comms_usb
diff --git a/lib/support/lib/libluausb.so b/lib/support/lib/libluausb.so
new file mode 100755
index 0000000..a7c9406
--- /dev/null
+++ b/lib/support/lib/libluausb.so
Binary files differ
diff --git a/lib/support/lib/lua_serialcomm.so b/lib/support/lib/lua_serialcomm.so
new file mode 100755
index 0000000..cb79295
--- /dev/null
+++ b/lib/support/lib/lua_serialcomm.so
Binary files differ
diff --git a/lib/support/lib/mime/core.so b/lib/support/lib/mime/core.so
new file mode 100755
index 0000000..696b7d9
--- /dev/null
+++ b/lib/support/lib/mime/core.so
Binary files differ
diff --git a/lib/support/lib/socket/core.so b/lib/support/lib/socket/core.so
new file mode 100755
index 0000000..ddfc8c3
--- /dev/null
+++ b/lib/support/lib/socket/core.so
Binary files differ
diff --git a/lib/support/libluausb.so b/lib/support/libluausb.so
new file mode 100755
index 0000000..a7c9406
--- /dev/null
+++ b/lib/support/libluausb.so
Binary files differ
diff --git a/lib/support/lua b/lib/support/lua
new file mode 100755
index 0000000..a36f550
--- /dev/null
+++ b/lib/support/lua
Binary files differ
diff --git a/lib/support/lua_serialcomm.so b/lib/support/lua_serialcomm.so
new file mode 100755
index 0000000..cb79295
--- /dev/null
+++ b/lib/support/lua_serialcomm.so
Binary files differ
diff --git a/lib/support/share/ltn12.lua b/lib/support/share/ltn12.lua
new file mode 100644
index 0000000..b42689a
--- /dev/null
+++ b/lib/support/share/ltn12.lua
@@ -0,0 +1,292 @@
+-----------------------------------------------------------------------------
+-- LTN12 - Filters, sources, sinks and pumps.
+-- LuaSocket toolkit.
+-- Author: Diego Nehab
+-- RCS ID: $Id: ltn12.lua,v 1.31 2006/04/03 04:45:42 diego Exp $
+-----------------------------------------------------------------------------
+
+-----------------------------------------------------------------------------
+-- Declare module
+-----------------------------------------------------------------------------
+local string = require("string")
+local table = require("table")
+local base = _G
+module("ltn12")
+
+filter = {}
+source = {}
+sink = {}
+pump = {}
+
+-- 2048 seems to be better in windows...
+BLOCKSIZE = 2048
+_VERSION = "LTN12 1.0.1"
+
+-----------------------------------------------------------------------------
+-- Filter stuff
+-----------------------------------------------------------------------------
+-- returns a high level filter that cycles a low-level filter
+function filter.cycle(low, ctx, extra)
+ base.assert(low)
+ return function(chunk)
+ local ret
+ ret, ctx = low(ctx, chunk, extra)
+ return ret
+ end
+end
+
+-- chains a bunch of filters together
+-- (thanks to Wim Couwenberg)
+function filter.chain(...)
+ local n = table.getn(arg)
+ local top, index = 1, 1
+ local retry = ""
+ return function(chunk)
+ retry = chunk and retry
+ while true do
+ if index == top then
+ chunk = arg[index](chunk)
+ if chunk == "" or top == n then return chunk
+ elseif chunk then index = index + 1
+ else
+ top = top+1
+ index = top
+ end
+ else
+ chunk = arg[index](chunk or "")
+ if chunk == "" then
+ index = index - 1
+ chunk = retry
+ elseif chunk then
+ if index == n then return chunk
+ else index = index + 1 end
+ else base.error("filter returned inappropriate nil") end
+ end
+ end
+ end
+end
+
+-----------------------------------------------------------------------------
+-- Source stuff
+-----------------------------------------------------------------------------
+-- create an empty source
+local function empty()
+ return nil
+end
+
+function source.empty()
+ return empty
+end
+
+-- returns a source that just outputs an error
+function source.error(err)
+ return function()
+ return nil, err
+ end
+end
+
+-- creates a file source
+function source.file(handle, io_err)
+ if handle then
+ return function()
+ local chunk = handle:read(BLOCKSIZE)
+ if not chunk then handle:close() end
+ return chunk
+ end
+ else return source.error(io_err or "unable to open file") end
+end
+
+-- turns a fancy source into a simple source
+function source.simplify(src)
+ base.assert(src)
+ return function()
+ local chunk, err_or_new = src()
+ src = err_or_new or src
+ if not chunk then return nil, err_or_new
+ else return chunk end
+ end
+end
+
+-- creates string source
+function source.string(s)
+ if s then
+ local i = 1
+ return function()
+ local chunk = string.sub(s, i, i+BLOCKSIZE-1)
+ i = i + BLOCKSIZE
+ if chunk ~= "" then return chunk
+ else return nil end
+ end
+ else return source.empty() end
+end
+
+-- creates rewindable source
+function source.rewind(src)
+ base.assert(src)
+ local t = {}
+ return function(chunk)
+ if not chunk then
+ chunk = table.remove(t)
+ if not chunk then return src()
+ else return chunk end
+ else
+ table.insert(t, chunk)
+ end
+ end
+end
+
+function source.chain(src, f)
+ base.assert(src and f)
+ local last_in, last_out = "", ""
+ local state = "feeding"
+ local err
+ return function()
+ if not last_out then
+ base.error('source is empty!', 2)
+ end
+ while true do
+ if state == "feeding" then
+ last_in, err = src()
+ if err then return nil, err end
+ last_out = f(last_in)
+ if not last_out then
+ if last_in then
+ base.error('filter returned inappropriate nil')
+ else
+ return nil
+ end
+ elseif last_out ~= "" then
+ state = "eating"
+ if last_in then last_in = "" end
+ return last_out
+ end
+ else
+ last_out = f(last_in)
+ if last_out == "" then
+ if last_in == "" then
+ state = "feeding"
+ else
+ base.error('filter returned ""')
+ end
+ elseif not last_out then
+ if last_in then
+ base.error('filter returned inappropriate nil')
+ else
+ return nil
+ end
+ else
+ return last_out
+ end
+ end
+ end
+ end
+end
+
+-- creates a source that produces contents of several sources, one after the
+-- other, as if they were concatenated
+-- (thanks to Wim Couwenberg)
+function source.cat(...)
+ local src = table.remove(arg, 1)
+ return function()
+ while src do
+ local chunk, err = src()
+ if chunk then return chunk end
+ if err then return nil, err end
+ src = table.remove(arg, 1)
+ end
+ end
+end
+
+-----------------------------------------------------------------------------
+-- Sink stuff
+-----------------------------------------------------------------------------
+-- creates a sink that stores into a table
+function sink.table(t)
+ t = t or {}
+ local f = function(chunk, err)
+ if chunk then table.insert(t, chunk) end
+ return 1
+ end
+ return f, t
+end
+
+-- turns a fancy sink into a simple sink
+function sink.simplify(snk)
+ base.assert(snk)
+ return function(chunk, err)
+ local ret, err_or_new = snk(chunk, err)
+ if not ret then return nil, err_or_new end
+ snk = err_or_new or snk
+ return 1
+ end
+end
+
+-- creates a file sink
+function sink.file(handle, io_err)
+ if handle then
+ return function(chunk, err)
+ if not chunk then
+ handle:close()
+ return 1
+ else return handle:write(chunk) end
+ end
+ else return sink.error(io_err or "unable to open file") end
+end
+
+-- creates a sink that discards data
+local function null()
+ return 1
+end
+
+function sink.null()
+ return null
+end
+
+-- creates a sink that just returns an error
+function sink.error(err)
+ return function()
+ return nil, err
+ end
+end
+
+-- chains a sink with a filter
+function sink.chain(f, snk)
+ base.assert(f and snk)
+ return function(chunk, err)
+ if chunk ~= "" then
+ local filtered = f(chunk)
+ local done = chunk and ""
+ while true do
+ local ret, snkerr = snk(filtered, err)
+ if not ret then return nil, snkerr end
+ if filtered == done then return 1 end
+ filtered = f(done)
+ end
+ else return 1 end
+ end
+end
+
+-----------------------------------------------------------------------------
+-- Pump stuff
+-----------------------------------------------------------------------------
+-- pumps one chunk from the source to the sink
+function pump.step(src, snk)
+ local chunk, src_err = src()
+ local ret, snk_err = snk(chunk, src_err)
+ if chunk and ret then return 1
+ else return nil, src_err or snk_err end
+end
+
+-- pumps all data from a source to a sink, using a step function
+function pump.all(src, snk, step)
+ base.assert(src and snk)
+ step = step or pump.step
+ while true do
+ local ret, err = step(src, snk)
+ if not ret then
+ if err then return nil, err
+ else return 1 end
+ end
+ end
+end
+
diff --git a/lib/support/share/mime.lua b/lib/support/share/mime.lua
new file mode 100644
index 0000000..169eda2
--- /dev/null
+++ b/lib/support/share/mime.lua
@@ -0,0 +1,87 @@
+-----------------------------------------------------------------------------
+-- MIME support for the Lua language.
+-- Author: Diego Nehab
+-- Conforming to RFCs 2045-2049
+-- RCS ID: $Id: mime.lua,v 1.29 2007/06/11 23:44:54 diego Exp $
+-----------------------------------------------------------------------------
+
+-----------------------------------------------------------------------------
+-- Declare module and import dependencies
+-----------------------------------------------------------------------------
+local base = _G
+local ltn12 = require("ltn12")
+local mime = require("mime.core")
+local io = require("io")
+local string = require("string")
+module("mime")
+
+-- encode, decode and wrap algorithm tables
+encodet = {}
+decodet = {}
+wrapt = {}
+
+-- creates a function that chooses a filter by name from a given table
+local function choose(table)
+ return function(name, opt1, opt2)
+ if base.type(name) ~= "string" then
+ name, opt1, opt2 = "default", name, opt1
+ end
+ local f = table[name or "nil"]
+ if not f then
+ base.error("unknown key (" .. base.tostring(name) .. ")", 3)
+ else return f(opt1, opt2) end
+ end
+end
+
+-- define the encoding filters
+encodet['base64'] = function()
+ return ltn12.filter.cycle(b64, "")
+end
+
+encodet['quoted-printable'] = function(mode)
+ return ltn12.filter.cycle(qp, "",
+ (mode == "binary") and "=0D=0A" or "\r\n")
+end
+
+-- define the decoding filters
+decodet['base64'] = function()
+ return ltn12.filter.cycle(unb64, "")
+end
+
+decodet['quoted-printable'] = function()
+ return ltn12.filter.cycle(unqp, "")
+end
+
+local function format(chunk)
+ if chunk then
+ if chunk == "" then return "''"
+ else return string.len(chunk) end
+ else return "nil" end
+end
+
+-- define the line-wrap filters
+wrapt['text'] = function(length)
+ length = length or 76
+ return ltn12.filter.cycle(wrp, length, length)
+end
+wrapt['base64'] = wrapt['text']
+wrapt['default'] = wrapt['text']
+
+wrapt['quoted-printable'] = function()
+ return ltn12.filter.cycle(qpwrp, 76, 76)
+end
+
+-- function that choose the encoding, decoding or wrap algorithm
+encode = choose(encodet)
+decode = choose(decodet)
+wrap = choose(wrapt)
+
+-- define the end-of-line normalization filter
+function normalize(marker)
+ return ltn12.filter.cycle(eol, 0, marker)
+end
+
+-- high level stuffing filter
+function stuff()
+ return ltn12.filter.cycle(dot, 2)
+end
diff --git a/lib/support/share/socket.lua b/lib/support/share/socket.lua
new file mode 100644
index 0000000..211adcd
--- /dev/null
+++ b/lib/support/share/socket.lua
@@ -0,0 +1,133 @@
+-----------------------------------------------------------------------------
+-- LuaSocket helper module
+-- Author: Diego Nehab
+-- RCS ID: $Id: socket.lua,v 1.22 2005/11/22 08:33:29 diego Exp $
+-----------------------------------------------------------------------------
+
+-----------------------------------------------------------------------------
+-- Declare module and import dependencies
+-----------------------------------------------------------------------------
+local base = _G
+local string = require("string")
+local math = require("math")
+local socket = require("socket.core")
+module("socket")
+
+-----------------------------------------------------------------------------
+-- Exported auxiliar functions
+-----------------------------------------------------------------------------
+function connect(address, port, laddress, lport)
+ local sock, err = socket.tcp()
+ if not sock then return nil, err end
+ if laddress then
+ local res, err = sock:bind(laddress, lport, -1)
+ if not res then return nil, err end
+ end
+ local res, err = sock:connect(address, port)
+ if not res then return nil, err end
+ return sock
+end
+
+function bind(host, port, backlog)
+ local sock, err = socket.tcp()
+ if not sock then return nil, err end
+ sock:setoption("reuseaddr", true)
+ local res, err = sock:bind(host, port)
+ if not res then return nil, err end
+ res, err = sock:listen(backlog)
+ if not res then return nil, err end
+ return sock
+end
+
+try = newtry()
+
+function choose(table)
+ return function(name, opt1, opt2)
+ if base.type(name) ~= "string" then
+ name, opt1, opt2 = "default", name, opt1
+ end
+ local f = table[name or "nil"]
+ if not f then base.error("unknown key (".. base.tostring(name) ..")", 3)
+ else return f(opt1, opt2) end
+ end
+end
+
+-----------------------------------------------------------------------------
+-- Socket sources and sinks, conforming to LTN12
+-----------------------------------------------------------------------------
+-- create namespaces inside LuaSocket namespace
+sourcet = {}
+sinkt = {}
+
+BLOCKSIZE = 2048
+
+sinkt["close-when-done"] = function(sock)
+ return base.setmetatable({
+ getfd = function() return sock:getfd() end,
+ dirty = function() return sock:dirty() end
+ }, {
+ __call = function(self, chunk, err)
+ if not chunk then
+ sock:close()
+ return 1
+ else return sock:send(chunk) end
+ end
+ })
+end
+
+sinkt["keep-open"] = function(sock)
+ return base.setmetatable({
+ getfd = function() return sock:getfd() end,
+ dirty = function() return sock:dirty() end
+ }, {
+ __call = function(self, chunk, err)
+ if chunk then return sock:send(chunk)
+ else return 1 end
+ end
+ })
+end
+
+sinkt["default"] = sinkt["keep-open"]
+
+sink = choose(sinkt)
+
+sourcet["by-length"] = function(sock, length)
+ return base.setmetatable({
+ getfd = function() return sock:getfd() end,
+ dirty = function() return sock:dirty() end
+ }, {
+ __call = function()
+ if length <= 0 then return nil end
+ local size = math.min(socket.BLOCKSIZE, length)
+ local chunk, err = sock:receive(size)
+ if err then return nil, err end
+ length = length - string.len(chunk)
+ return chunk
+ end
+ })
+end
+
+sourcet["until-closed"] = function(sock)
+ local done
+ return base.setmetatable({
+ getfd = function() return sock:getfd() end,
+ dirty = function() return sock:dirty() end
+ }, {
+ __call = function()
+ if done then return nil end
+ local chunk, err, partial = sock:receive(socket.BLOCKSIZE)
+ if not err then return chunk
+ elseif err == "closed" then
+ sock:close()
+ done = 1
+ return partial
+ else return nil, err end
+ end
+ })
+end
+
+
+sourcet["default"] = sourcet["until-closed"]
+
+source = choose(sourcet)
+
diff --git a/lib/support/share/socket/ftp.lua b/lib/support/share/socket/ftp.lua
new file mode 100644
index 0000000..598f65d
--- /dev/null
+++ b/lib/support/share/socket/ftp.lua
@@ -0,0 +1,281 @@
+-----------------------------------------------------------------------------
+-- FTP support for the Lua language
+-- LuaSocket toolkit.
+-- Author: Diego Nehab
+-- RCS ID: $Id: ftp.lua,v 1.45 2007/07/11 19:25:47 diego Exp $
+-----------------------------------------------------------------------------
+
+-----------------------------------------------------------------------------
+-- Declare module and import dependencies
+-----------------------------------------------------------------------------
+local base = _G
+local table = require("table")
+local string = require("string")
+local math = require("math")
+local socket = require("socket")
+local url = require("socket.url")
+local tp = require("socket.tp")
+local ltn12 = require("ltn12")
+module("socket.ftp")
+
+-----------------------------------------------------------------------------
+-- Program constants
+-----------------------------------------------------------------------------
+-- timeout in seconds before the program gives up on a connection
+TIMEOUT = 60
+-- default port for ftp service
+PORT = 21
+-- this is the default anonymous password. used when no password is
+-- provided in url. should be changed to your e-mail.
+USER = "ftp"
+PASSWORD = "anonymous@anonymous.org"
+
+-----------------------------------------------------------------------------
+-- Low level FTP API
+-----------------------------------------------------------------------------
+local metat = { __index = {} }
+
+function open(server, port, create)
+ local tp = socket.try(tp.connect(server, port or PORT, TIMEOUT, create))
+ local f = base.setmetatable({ tp = tp }, metat)
+ -- make sure everything gets closed in an exception
+ f.try = socket.newtry(function() f:close() end)
+ return f
+end
+
+function metat.__index:portconnect()
+ self.try(self.server:settimeout(TIMEOUT))
+ self.data = self.try(self.server:accept())
+ self.try(self.data:settimeout(TIMEOUT))
+end
+
+function metat.__index:pasvconnect()
+ self.data = self.try(socket.tcp())
+ self.try(self.data:settimeout(TIMEOUT))
+ self.try(self.data:connect(self.pasvt.ip, self.pasvt.port))
+end
+
+function metat.__index:login(user, password)
+ self.try(self.tp:command("user", user or USER))
+ local code, reply = self.try(self.tp:check{"2..", 331})
+ if code == 331 then
+ self.try(self.tp:command("pass", password or PASSWORD))
+ self.try(self.tp:check("2.."))
+ end
+ return 1
+end
+
+function metat.__index:pasv()
+ self.try(self.tp:command("pasv"))
+ local code, reply = self.try(self.tp:check("2.."))
+ local pattern = "(%d+)%D(%d+)%D(%d+)%D(%d+)%D(%d+)%D(%d+)"
+ local a, b, c, d, p1, p2 = socket.skip(2, string.find(reply, pattern))
+ self.try(a and b and c and d and p1 and p2, reply)
+ self.pasvt = {
+ ip = string.format("%d.%d.%d.%d", a, b, c, d),
+ port = p1*256 + p2
+ }
+ if self.server then
+ self.server:close()
+ self.server = nil
+ end
+ return self.pasvt.ip, self.pasvt.port
+end
+
+function metat.__index:port(ip, port)
+ self.pasvt = nil
+ if not ip then
+ ip, port = self.try(self.tp:getcontrol():getsockname())
+ self.server = self.try(socket.bind(ip, 0))
+ ip, port = self.try(self.server:getsockname())
+ self.try(self.server:settimeout(TIMEOUT))
+ end
+ local pl = math.mod(port, 256)
+ local ph = (port - pl)/256
+ local arg = string.gsub(string.format("%s,%d,%d", ip, ph, pl), "%.", ",")
+ self.try(self.tp:command("port", arg))
+ self.try(self.tp:check("2.."))
+ return 1
+end
+
+function metat.__index:send(sendt)
+ self.try(self.pasvt or self.server, "need port or pasv first")
+ -- if there is a pasvt table, we already sent a PASV command
+ -- we just get the data connection into self.data
+ if self.pasvt then self:pasvconnect() end
+ -- get the transfer argument and command
+ local argument = sendt.argument or
+ url.unescape(string.gsub(sendt.path or "", "^[/\\]", ""))
+ if argument == "" then argument = nil end
+ local command = sendt.command or "stor"
+ -- send the transfer command and check the reply
+ self.try(self.tp:command(command, argument))
+ local code, reply = self.try(self.tp:check{"2..", "1.."})
+ -- if there is not a a pasvt table, then there is a server
+ -- and we already sent a PORT command
+ if not self.pasvt then self:portconnect() end
+ -- get the sink, source and step for the transfer
+ local step = sendt.step or ltn12.pump.step
+ local readt = {self.tp.c}
+ local checkstep = function(src, snk)
+ -- check status in control connection while downloading
+ local readyt = socket.select(readt, nil, 0)
+ if readyt[tp] then code = self.try(self.tp:check("2..")) end
+ return step(src, snk)
+ end
+ local sink = socket.sink("close-when-done", self.data)
+ -- transfer all data and check error
+ self.try(ltn12.pump.all(sendt.source, sink, checkstep))
+ if string.find(code, "1..") then self.try(self.tp:check("2..")) end
+ -- done with data connection
+ self.data:close()
+ -- find out how many bytes were sent
+ local sent = socket.skip(1, self.data:getstats())
+ self.data = nil
+ return sent
+end
+
+function metat.__index:receive(recvt)
+ self.try(self.pasvt or self.server, "need port or pasv first")
+ if self.pasvt then self:pasvconnect() end
+ local argument = recvt.argument or
+ url.unescape(string.gsub(recvt.path or "", "^[/\\]", ""))
+ if argument == "" then argument = nil end
+ local command = recvt.command or "retr"
+ self.try(self.tp:command(command, argument))
+ local code = self.try(self.tp:check{"1..", "2.."})
+ if not self.pasvt then self:portconnect() end
+ local source = socket.source("until-closed", self.data)
+ local step = recvt.step or ltn12.pump.step
+ self.try(ltn12.pump.all(source, recvt.sink, step))
+ if string.find(code, "1..") then self.try(self.tp:check("2..")) end
+ self.data:close()
+ self.data = nil
+ return 1
+end
+
+function metat.__index:cwd(dir)
+ self.try(self.tp:command("cwd", dir))
+ self.try(self.tp:check(250))
+ return 1
+end
+
+function metat.__index:type(type)
+ self.try(self.tp:command("type", type))
+ self.try(self.tp:check(200))
+ return 1
+end
+
+function metat.__index:greet()
+ local code = self.try(self.tp:check{"1..", "2.."})
+ if string.find(code, "1..") then self.try(self.tp:check("2..")) end
+ return 1
+end
+
+function metat.__index:quit()
+ self.try(self.tp:command("quit"))
+ self.try(self.tp:check("2.."))
+ return 1
+end
+
+function metat.__index:close()
+ if self.data then self.data:close() end
+ if self.server then self.server:close() end
+ return self.tp:close()
+end
+
+-----------------------------------------------------------------------------
+-- High level FTP API
+-----------------------------------------------------------------------------
+local function override(t)
+ if t.url then
+ local u = url.parse(t.url)
+ for i,v in base.pairs(t) do
+ u[i] = v
+ end
+ return u
+ else return t end
+end
+
+local function tput(putt)
+ putt = override(putt)
+ socket.try(putt.host, "missing hostname")
+ local f = open(putt.host, putt.port, putt.create)
+ f:greet()
+ f:login(putt.user, putt.password)
+ if putt.type then f:type(putt.type) end
+ f:pasv()
+ local sent = f:send(putt)
+ f:quit()
+ f:close()
+ return sent
+end
+
+local default = {
+ path = "/",
+ scheme = "ftp"
+}
+
+local function parse(u)
+ local t = socket.try(url.parse(u, default))
+ socket.try(t.scheme == "ftp", "wrong scheme '" .. t.scheme .. "'")
+ socket.try(t.host, "missing hostname")
+ local pat = "^type=(.)$"
+ if t.params then
+ t.type = socket.skip(2, string.find(t.params, pat))
+ socket.try(t.type == "a" or t.type == "i",
+ "invalid type '" .. t.type .. "'")
+ end
+ return t
+end
+
+local function sput(u, body)
+ local putt = parse(u)
+ putt.source = ltn12.source.string(body)
+ return tput(putt)
+end
+
+put = socket.protect(function(putt, body)
+ if base.type(putt) == "string" then return sput(putt, body)
+ else return tput(putt) end
+end)
+
+local function tget(gett)
+ gett = override(gett)
+ socket.try(gett.host, "missing hostname")
+ local f = open(gett.host, gett.port, gett.create)
+ f:greet()
+ f:login(gett.user, gett.password)
+ if gett.type then f:type(gett.type) end
+ f:pasv()
+ f:receive(gett)
+ f:quit()
+ return f:close()
+end
+
+local function sget(u)
+ local gett = parse(u)
+ local t = {}
+ gett.sink = ltn12.sink.table(t)
+ tget(gett)
+ return table.concat(t)
+end
+
+command = socket.protect(function(cmdt)
+ cmdt = override(cmdt)
+ socket.try(cmdt.host, "missing hostname")
+ socket.try(cmdt.command, "missing command")
+ local f = open(cmdt.host, cmdt.port, cmdt.create)
+ f:greet()
+ f:login(cmdt.user, cmdt.password)
+ f.try(f.tp:command(cmdt.command, cmdt.argument))
+ if cmdt.check then f.try(f.tp:check(cmdt.check)) end
+ f:quit()
+ return f:close()
+end)
+
+get = socket.protect(function(gett)
+ if base.type(gett) == "string" then return sget(gett)
+ else return tget(gett) end
+end)
+
diff --git a/lib/support/share/socket/http.lua b/lib/support/share/socket/http.lua
new file mode 100644
index 0000000..ad8db1e
--- /dev/null
+++ b/lib/support/share/socket/http.lua
@@ -0,0 +1,350 @@
+-----------------------------------------------------------------------------
+-- HTTP/1.1 client support for the Lua language.
+-- LuaSocket toolkit.
+-- Author: Diego Nehab
+-- RCS ID: $Id: http.lua,v 1.71 2007/10/13 23:55:20 diego Exp $
+-----------------------------------------------------------------------------
+
+-----------------------------------------------------------------------------
+-- Declare module and import dependencies
+-------------------------------------------------------------------------------
+local socket = require("socket")
+local url = require("socket.url")
+local ltn12 = require("ltn12")
+local mime = require("mime")
+local string = require("string")
+local base = _G
+local table = require("table")
+module("socket.http")
+
+-----------------------------------------------------------------------------
+-- Program constants
+-----------------------------------------------------------------------------
+-- connection timeout in seconds
+TIMEOUT = 60
+-- default port for document retrieval
+PORT = 80
+-- user agent field sent in request
+USERAGENT = socket._VERSION
+
+-----------------------------------------------------------------------------
+-- Reads MIME headers from a connection, unfolding where needed
+-----------------------------------------------------------------------------
+local function receiveheaders(sock, headers)
+ local line, name, value, err
+ headers = headers or {}
+ -- get first line
+ line, err = sock:receive()
+ if err then return nil, err end
+ -- headers go until a blank line is found
+ while line ~= "" do
+ -- get field-name and value
+ name, value = socket.skip(2, string.find(line, "^(.-):%s*(.*)"))
+ if not (name and value) then return nil, "malformed reponse headers" end
+ name = string.lower(name)
+ -- get next line (value might be folded)
+ line, err = sock:receive()
+ if err then return nil, err end
+ -- unfold any folded values
+ while string.find(line, "^%s") do
+ value = value .. line
+ line = sock:receive()
+ if err then return nil, err end
+ end
+ -- save pair in table
+ if headers[name] then headers[name] = headers[name] .. ", " .. value
+ else headers[name] = value end
+ end
+ return headers
+end
+
+-----------------------------------------------------------------------------
+-- Extra sources and sinks
+-----------------------------------------------------------------------------
+socket.sourcet["http-chunked"] = function(sock, headers)
+ return base.setmetatable({
+ getfd = function() return sock:getfd() end,
+ dirty = function() return sock:dirty() end
+ }, {
+ __call = function()
+ -- get chunk size, skip extention
+ local line, err = sock:receive()
+ if err then return nil, err end
+ local size = base.tonumber(string.gsub(line, ";.*", ""), 16)
+ if not size then return nil, "invalid chunk size" end
+ -- was it the last chunk?
+ if size > 0 then
+ -- if not, get chunk and skip terminating CRLF
+ local chunk, err, part = sock:receive(size)
+ if chunk then sock:receive() end
+ return chunk, err
+ else
+ -- if it was, read trailers into headers table
+ headers, err = receiveheaders(sock, headers)
+ if not headers then return nil, err end
+ end
+ end
+ })
+end
+
+socket.sinkt["http-chunked"] = function(sock)
+ return base.setmetatable({
+ getfd = function() return sock:getfd() end,
+ dirty = function() return sock:dirty() end
+ }, {
+ __call = function(self, chunk, err)
+ if not chunk then return sock:send("0\r\n\r\n") end
+ local size = string.format("%X\r\n", string.len(chunk))
+ return sock:send(size .. chunk .. "\r\n")
+ end
+ })
+end
+
+-----------------------------------------------------------------------------
+-- Low level HTTP API
+-----------------------------------------------------------------------------
+local metat = { __index = {} }
+
+function open(host, port, create)
+ -- create socket with user connect function, or with default
+ local c = socket.try((create or socket.tcp)())
+ local h = base.setmetatable({ c = c }, metat)
+ -- create finalized try
+ h.try = socket.newtry(function() h:close() end)
+ -- set timeout before connecting
+ h.try(c:settimeout(TIMEOUT))
+ h.try(c:connect(host, port or PORT))
+ -- here everything worked
+ return h
+end
+
+function metat.__index:sendrequestline(method, uri)
+ local reqline = string.format("%s %s HTTP/1.1\r\n", method or "GET", uri)
+ return self.try(self.c:send(reqline))
+end
+
+function metat.__index:sendheaders(headers)
+ local h = "\r\n"
+ for i, v in base.pairs(headers) do
+ h = i .. ": " .. v .. "\r\n" .. h
+ end
+ self.try(self.c:send(h))
+ return 1
+end
+
+function metat.__index:sendbody(headers, source, step)
+ source = source or ltn12.source.empty()
+ step = step or ltn12.pump.step
+ -- if we don't know the size in advance, send chunked and hope for the best
+ local mode = "http-chunked"
+ if headers["content-length"] then mode = "keep-open" end
+ return self.try(ltn12.pump.all(source, socket.sink(mode, self.c), step))
+end
+
+function metat.__index:receivestatusline()
+ local status = self.try(self.c:receive(5))
+ -- identify HTTP/0.9 responses, which do not contain a status line
+ -- this is just a heuristic, but is what the RFC recommends
+ if status ~= "HTTP/" then return nil, status end
+ -- otherwise proceed reading a status line
+ status = self.try(self.c:receive("*l", status))
+ local code = socket.skip(2, string.find(status, "HTTP/%d*%.%d* (%d%d%d)"))
+ return self.try(base.tonumber(code), status)
+end
+
+function metat.__index:receiveheaders()
+ return self.try(receiveheaders(self.c))
+end
+
+function metat.__index:receivebody(headers, sink, step)
+ sink = sink or ltn12.sink.null()
+ step = step or ltn12.pump.step
+ local length = base.tonumber(headers["content-length"])
+ local t = headers["transfer-encoding"] -- shortcut
+ local mode = "default" -- connection close
+ if t and t ~= "identity" then mode = "http-chunked"
+ elseif base.tonumber(headers["content-length"]) then mode = "by-length" end
+ return self.try(ltn12.pump.all(socket.source(mode, self.c, length),
+ sink, step))
+end
+
+function metat.__index:receive09body(status, sink, step)
+ local source = ltn12.source.rewind(socket.source("until-closed", self.c))
+ source(status)
+ return self.try(ltn12.pump.all(source, sink, step))
+end
+
+function metat.__index:close()
+ return self.c:close()
+end
+
+-----------------------------------------------------------------------------
+-- High level HTTP API
+-----------------------------------------------------------------------------
+local function adjusturi(reqt)
+ local u = reqt
+ -- if there is a proxy, we need the full url. otherwise, just a part.
+ if not reqt.proxy and not PROXY then
+ u = {
+ path = socket.try(reqt.path, "invalid path 'nil'"),
+ params = reqt.params,
+ query = reqt.query,
+ fragment = reqt.fragment
+ }
+ end
+ return url.build(u)
+end
+
+local function adjustproxy(reqt)
+ local proxy = reqt.proxy or PROXY
+ if proxy then
+ proxy = url.parse(proxy)
+ return proxy.host, proxy.port or 3128
+ else
+ return reqt.host, reqt.port
+ end
+end
+
+local function adjustheaders(reqt)
+ -- default headers
+ local lower = {
+ ["user-agent"] = USERAGENT,
+ ["host"] = reqt.host,
+ ["connection"] = "close, TE",
+ ["te"] = "trailers"
+ }
+ -- if we have authentication information, pass it along
+ if reqt.user and reqt.password then
+ lower["authorization"] =
+ "Basic " .. (mime.b64(reqt.user .. ":" .. reqt.password))
+ end
+ -- override with user headers
+ for i,v in base.pairs(reqt.headers or lower) do
+ lower[string.lower(i)] = v
+ end
+ return lower
+end
+
+-- default url parts
+local default = {
+ host = "",
+ port = PORT,
+ path ="/",
+ scheme = "http"
+}
+
+local function adjustrequest(reqt)
+ -- parse url if provided
+ local nreqt = reqt.url and url.parse(reqt.url, default) or {}
+ -- explicit components override url
+ for i,v in base.pairs(reqt) do nreqt[i] = v end
+ if nreqt.port == "" then nreqt.port = 80 end
+ socket.try(nreqt.host and nreqt.host ~= "",
+ "invalid host '" .. base.tostring(nreqt.host) .. "'")
+ -- compute uri if user hasn't overriden
+ nreqt.uri = reqt.uri or adjusturi(nreqt)
+ -- ajust host and port if there is a proxy
+ nreqt.host, nreqt.port = adjustproxy(nreqt)
+ -- adjust headers in request
+ nreqt.headers = adjustheaders(nreqt)
+ return nreqt
+end
+
+local function shouldredirect(reqt, code, headers)
+ return headers.location and
+ string.gsub(headers.location, "%s", "") ~= "" and
+ (reqt.redirect ~= false) and
+ (code == 301 or code == 302) and
+ (not reqt.method or reqt.method == "GET" or reqt.method == "HEAD")
+ and (not reqt.nredirects or reqt.nredirects < 5)
+end
+
+local function shouldreceivebody(reqt, code)
+ if reqt.method == "HEAD" then return nil end
+ if code == 204 or code == 304 then return nil end
+ if code >= 100 and code < 200 then return nil end
+ return 1
+end
+
+-- forward declarations
+local trequest, tredirect
+
+function tredirect(reqt, location)
+ local result, code, headers, status = trequest {
+ -- the RFC says the redirect URL has to be absolute, but some
+ -- servers do not respect that
+ url = url.absolute(reqt.url, location),
+ source = reqt.source,
+ sink = reqt.sink,
+ headers = reqt.headers,
+ proxy = reqt.proxy,
+ nredirects = (reqt.nredirects or 0) + 1,
+ create = reqt.create
+ }
+ -- pass location header back as a hint we redirected
+ headers = headers or {}
+ headers.location = headers.location or location
+ return result, code, headers, status
+end
+
+function trequest(reqt)
+ -- we loop until we get what we want, or
+ -- until we are sure there is no way to get it
+ local nreqt = adjustrequest(reqt)
+ local h = open(nreqt.host, nreqt.port, nreqt.create)
+ -- send request line and headers
+ h:sendrequestline(nreqt.method, nreqt.uri)
+ h:sendheaders(nreqt.headers)
+ -- if there is a body, send it
+ if nreqt.source then
+ h:sendbody(nreqt.headers, nreqt.source, nreqt.step)
+ end
+ local code, status = h:receivestatusline()
+ -- if it is an HTTP/0.9 server, simply get the body and we are done
+ if not code then
+ h:receive09body(status, nreqt.sink, nreqt.step)
+ return 1, 200
+ end
+ local headers
+ -- ignore any 100-continue messages
+ while code == 100 do
+ headers = h:receiveheaders()
+ code, status = h:receivestatusline()
+ end
+ headers = h:receiveheaders()
+ -- at this point we should have a honest reply from the server
+ -- we can't redirect if we already used the source, so we report the error
+ if shouldredirect(nreqt, code, headers) and not nreqt.source then
+ h:close()
+ return tredirect(reqt, headers.location)
+ end
+ -- here we are finally done
+ if shouldreceivebody(nreqt, code) then
+ h:receivebody(headers, nreqt.sink, nreqt.step)
+ end
+ h:close()
+ return 1, code, headers, status
+end
+
+local function srequest(u, b)
+ local t = {}
+ local reqt = {
+ url = u,
+ sink = ltn12.sink.table(t)
+ }
+ if b then
+ reqt.source = ltn12.source.string(b)
+ reqt.headers = {
+ ["content-length"] = string.len(b),
+ ["content-type"] = "application/x-www-form-urlencoded"
+ }
+ reqt.method = "POST"
+ end
+ local code, headers, status = socket.skip(1, trequest(reqt))
+ return table.concat(t), code, headers, status
+end
+
+request = socket.protect(function(reqt, body)
+ if base.type(reqt) == "string" then return srequest(reqt, body)
+ else return trequest(reqt) end
+end)
diff --git a/lib/support/share/socket/smtp.lua b/lib/support/share/socket/smtp.lua
new file mode 100644
index 0000000..8f3cfcf
--- /dev/null
+++ b/lib/support/share/socket/smtp.lua
@@ -0,0 +1,251 @@
+-----------------------------------------------------------------------------
+-- SMTP client support for the Lua language.
+-- LuaSocket toolkit.
+-- Author: Diego Nehab
+-- RCS ID: $Id: smtp.lua,v 1.46 2007/03/12 04:08:40 diego Exp $
+-----------------------------------------------------------------------------
+
+-----------------------------------------------------------------------------
+-- Declare module and import dependencies
+-----------------------------------------------------------------------------
+local base = _G
+local coroutine = require("coroutine")
+local string = require("string")
+local math = require("math")
+local os = require("os")
+local socket = require("socket")
+local tp = require("socket.tp")
+local ltn12 = require("ltn12")
+local mime = require("mime")
+module("socket.smtp")
+
+-----------------------------------------------------------------------------
+-- Program constants
+-----------------------------------------------------------------------------
+-- timeout for connection
+TIMEOUT = 60
+-- default server used to send e-mails
+SERVER = "localhost"
+-- default port
+PORT = 25
+-- domain used in HELO command and default sendmail
+-- If we are under a CGI, try to get from environment
+DOMAIN = os.getenv("SERVER_NAME") or "localhost"
+-- default time zone (means we don't know)
+ZONE = "-0000"
+
+---------------------------------------------------------------------------
+-- Low level SMTP API
+-----------------------------------------------------------------------------
+local metat = { __index = {} }
+
+function metat.__index:greet(domain)
+ self.try(self.tp:check("2.."))
+ self.try(self.tp:command("EHLO", domain or DOMAIN))
+ return socket.skip(1, self.try(self.tp:check("2..")))
+end
+
+function metat.__index:mail(from)
+ self.try(self.tp:command("MAIL", "FROM:" .. from))
+ return self.try(self.tp:check("2.."))
+end
+
+function metat.__index:rcpt(to)
+ self.try(self.tp:command("RCPT", "TO:" .. to))
+ return self.try(self.tp:check("2.."))
+end
+
+function metat.__index:data(src, step)
+ self.try(self.tp:command("DATA"))
+ self.try(self.tp:check("3.."))
+ self.try(self.tp:source(src, step))
+ self.try(self.tp:send("\r\n.\r\n"))
+ return self.try(self.tp:check("2.."))
+end
+
+function metat.__index:quit()
+ self.try(self.tp:command("QUIT"))
+ return self.try(self.tp:check("2.."))
+end
+
+function metat.__index:close()
+ return self.tp:close()
+end
+
+function metat.__index:login(user, password)
+ self.try(self.tp:command("AUTH", "LOGIN"))
+ self.try(self.tp:check("3.."))
+ self.try(self.tp:command(mime.b64(user)))
+ self.try(self.tp:check("3.."))
+ self.try(self.tp:command(mime.b64(password)))
+ return self.try(self.tp:check("2.."))
+end
+
+function metat.__index:plain(user, password)
+ local auth = "PLAIN " .. mime.b64("\0" .. user .. "\0" .. password)
+ self.try(self.tp:command("AUTH", auth))
+ return self.try(self.tp:check("2.."))
+end
+
+function metat.__index:auth(user, password, ext)
+ if not user or not password then return 1 end
+ if string.find(ext, "AUTH[^\n]+LOGIN") then
+ return self:login(user, password)
+ elseif string.find(ext, "AUTH[^\n]+PLAIN") then
+ return self:plain(user, password)
+ else
+ self.try(nil, "authentication not supported")
+ end
+end
+
+-- send message or throw an exception
+function metat.__index:send(mailt)
+ self:mail(mailt.from)
+ if base.type(mailt.rcpt) == "table" then
+ for i,v in base.ipairs(mailt.rcpt) do
+ self:rcpt(v)
+ end
+ else
+ self:rcpt(mailt.rcpt)
+ end
+ self:data(ltn12.source.chain(mailt.source, mime.stuff()), mailt.step)
+end
+
+function open(server, port, create)
+ local tp = socket.try(tp.connect(server or SERVER, port or PORT,
+ TIMEOUT, create))
+ local s = base.setmetatable({tp = tp}, metat)
+ -- make sure tp is closed if we get an exception
+ s.try = socket.newtry(function()
+ s:close()
+ end)
+ return s
+end
+
+-- convert headers to lowercase
+local function lower_headers(headers)
+ local lower = {}
+ for i,v in base.pairs(headers or lower) do
+ lower[string.lower(i)] = v
+ end
+ return lower
+end
+
+---------------------------------------------------------------------------
+-- Multipart message source
+-----------------------------------------------------------------------------
+-- returns a hopefully unique mime boundary
+local seqno = 0
+local function newboundary()
+ seqno = seqno + 1
+ return string.format('%s%05d==%05u', os.date('%d%m%Y%H%M%S'),
+ math.random(0, 99999), seqno)
+end
+
+-- send_message forward declaration
+local send_message
+
+-- yield the headers all at once, it's faster
+local function send_headers(headers)
+ local h = "\r\n"
+ for i,v in base.pairs(headers) do
+ h = i .. ': ' .. v .. "\r\n" .. h
+ end
+ coroutine.yield(h)
+end
+
+-- yield multipart message body from a multipart message table
+local function send_multipart(mesgt)
+ -- make sure we have our boundary and send headers
+ local bd = newboundary()
+ local headers = lower_headers(mesgt.headers or {})
+ headers['content-type'] = headers['content-type'] or 'multipart/mixed'
+ headers['content-type'] = headers['content-type'] ..
+ '; boundary="' .. bd .. '"'
+ send_headers(headers)
+ -- send preamble
+ if mesgt.body.preamble then
+ coroutine.yield(mesgt.body.preamble)
+ coroutine.yield("\r\n")
+ end
+ -- send each part separated by a boundary
+ for i, m in base.ipairs(mesgt.body) do
+ coroutine.yield("\r\n--" .. bd .. "\r\n")
+ send_message(m)
+ end
+ -- send last boundary
+ coroutine.yield("\r\n--" .. bd .. "--\r\n\r\n")
+ -- send epilogue
+ if mesgt.body.epilogue then
+ coroutine.yield(mesgt.body.epilogue)
+ coroutine.yield("\r\n")
+ end
+end
+
+-- yield message body from a source
+local function send_source(mesgt)
+ -- make sure we have a content-type
+ local headers = lower_headers(mesgt.headers or {})
+ headers['content-type'] = headers['content-type'] or
+ 'text/plain; charset="iso-8859-1"'
+ send_headers(headers)
+ -- send body from source
+ while true do
+ local chunk, err = mesgt.body()
+ if err then coroutine.yield(nil, err)
+ elseif chunk then coroutine.yield(chunk)
+ else break end
+ end
+end
+
+-- yield message body from a string
+local function send_string(mesgt)
+ -- make sure we have a content-type
+ local headers = lower_headers(mesgt.headers or {})
+ headers['content-type'] = headers['content-type'] or
+ 'text/plain; charset="iso-8859-1"'
+ send_headers(headers)
+ -- send body from string
+ coroutine.yield(mesgt.body)
+end
+
+-- message source
+function send_message(mesgt)
+ if base.type(mesgt.body) == "table" then send_multipart(mesgt)
+ elseif base.type(mesgt.body) == "function" then send_source(mesgt)
+ else send_string(mesgt) end
+end
+
+-- set defaul headers
+local function adjust_headers(mesgt)
+ local lower = lower_headers(mesgt.headers)
+ lower["date"] = lower["date"] or
+ os.date("!%a, %d %b %Y %H:%M:%S ") .. (mesgt.zone or ZONE)
+ lower["x-mailer"] = lower["x-mailer"] or socket._VERSION
+ -- this can't be overriden
+ lower["mime-version"] = "1.0"
+ return lower
+end
+
+function message(mesgt)
+ mesgt.headers = adjust_headers(mesgt)
+ -- create and return message source
+ local co = coroutine.create(function() send_message(mesgt) end)
+ return function()
+ local ret, a, b = coroutine.resume(co)
+ if ret then return a, b
+ else return nil, a end
+ end
+end
+
+---------------------------------------------------------------------------
+-- High level SMTP API
+-----------------------------------------------------------------------------
+send = socket.protect(function(mailt)
+ local s = open(mailt.server, mailt.port, mailt.create)
+ local ext = s:greet(mailt.domain)
+ s:auth(mailt.user, mailt.password, ext)
+ s:send(mailt)
+ s:quit()
+ return s:close()
+end)
diff --git a/lib/support/share/socket/tp.lua b/lib/support/share/socket/tp.lua
new file mode 100644
index 0000000..0683869
--- /dev/null
+++ b/lib/support/share/socket/tp.lua
@@ -0,0 +1,123 @@
+-----------------------------------------------------------------------------
+-- Unified SMTP/FTP subsystem
+-- LuaSocket toolkit.
+-- Author: Diego Nehab
+-- RCS ID: $Id: tp.lua,v 1.22 2006/03/14 09:04:15 diego Exp $
+-----------------------------------------------------------------------------
+
+-----------------------------------------------------------------------------
+-- Declare module and import dependencies
+-----------------------------------------------------------------------------
+local base = _G
+local string = require("string")
+local socket = require("socket")
+local ltn12 = require("ltn12")
+module("socket.tp")
+
+-----------------------------------------------------------------------------
+-- Program constants
+-----------------------------------------------------------------------------
+TIMEOUT = 60
+
+-----------------------------------------------------------------------------
+-- Implementation
+-----------------------------------------------------------------------------
+-- gets server reply (works for SMTP and FTP)
+local function get_reply(c)
+ local code, current, sep
+ local line, err = c:receive()
+ local reply = line
+ if err then return nil, err end
+ code, sep = socket.skip(2, string.find(line, "^(%d%d%d)(.?)"))
+ if not code then return nil, "invalid server reply" end
+ if sep == "-" then -- reply is multiline
+ repeat
+ line, err = c:receive()
+ if err then return nil, err end
+ current, sep = socket.skip(2, string.find(line, "^(%d%d%d)(.?)"))
+ reply = reply .. "\n" .. line
+ -- reply ends with same code
+ until code == current and sep == " "
+ end
+ return code, reply
+end
+
+-- metatable for sock object
+local metat = { __index = {} }
+
+function metat.__index:check(ok)
+ local code, reply = get_reply(self.c)
+ if not code then return nil, reply end
+ if base.type(ok) ~= "function" then
+ if base.type(ok) == "table" then
+ for i, v in base.ipairs(ok) do
+ if string.find(code, v) then
+ return base.tonumber(code), reply
+ end
+ end
+ return nil, reply
+ else
+ if string.find(code, ok) then return base.tonumber(code), reply
+ else return nil, reply end
+ end
+ else return ok(base.tonumber(code), reply) end
+end
+
+function metat.__index:command(cmd, arg)
+ if arg then
+ return self.c:send(cmd .. " " .. arg.. "\r\n")
+ else
+ return self.c:send(cmd .. "\r\n")
+ end
+end
+
+function metat.__index:sink(snk, pat)
+ local chunk, err = c:receive(pat)
+ return snk(chunk, err)
+end
+
+function metat.__index:send(data)
+ return self.c:send(data)
+end
+
+function metat.__index:receive(pat)
+ return self.c:receive(pat)
+end
+
+function metat.__index:getfd()
+ return self.c:getfd()
+end
+
+function metat.__index:dirty()
+ return self.c:dirty()
+end
+
+function metat.__index:getcontrol()
+ return self.c
+end
+
+function metat.__index:source(source, step)
+ local sink = socket.sink("keep-open", self.c)
+ local ret, err = ltn12.pump.all(source, sink, step or ltn12.pump.step)
+ return ret, err
+end
+
+-- closes the underlying c
+function metat.__index:close()
+ self.c:close()
+ return 1
+end
+
+-- connect with server and return c object
+function connect(host, port, timeout, create)
+ local c, e = (create or socket.tcp)()
+ if not c then return nil, e end
+ c:settimeout(timeout or TIMEOUT)
+ local r, e = c:connect(host, port)
+ if not r then
+ c:close()
+ return nil, e
+ end
+ return base.setmetatable({c = c}, metat)
+end
+
diff --git a/lib/support/share/socket/url.lua b/lib/support/share/socket/url.lua
new file mode 100644
index 0000000..0e31d8a
--- /dev/null
+++ b/lib/support/share/socket/url.lua
@@ -0,0 +1,297 @@
+-----------------------------------------------------------------------------
+-- URI parsing, composition and relative URL resolution
+-- LuaSocket toolkit.
+-- Author: Diego Nehab
+-- RCS ID: $Id: url.lua,v 1.38 2006/04/03 04:45:42 diego Exp $
+-----------------------------------------------------------------------------
+
+-----------------------------------------------------------------------------
+-- Declare module
+-----------------------------------------------------------------------------
+local string = require("string")
+local base = _G
+local table = require("table")
+module("socket.url")
+
+-----------------------------------------------------------------------------
+-- Module version
+-----------------------------------------------------------------------------
+_VERSION = "URL 1.0.1"
+
+-----------------------------------------------------------------------------
+-- Encodes a string into its escaped hexadecimal representation
+-- Input
+-- s: binary string to be encoded
+-- Returns
+-- escaped representation of string binary
+-----------------------------------------------------------------------------
+function escape(s)
+ return string.gsub(s, "([^A-Za-z0-9_])", function(c)
+ return string.format("%%%02x", string.byte(c))
+ end)
+end
+
+-----------------------------------------------------------------------------
+-- Protects a path segment, to prevent it from interfering with the
+-- url parsing.
+-- Input
+-- s: binary string to be encoded
+-- Returns
+-- escaped representation of string binary
+-----------------------------------------------------------------------------
+local function make_set(t)
+ local s = {}
+ for i,v in base.ipairs(t) do
+ s[t[i]] = 1
+ end
+ return s
+end
+
+-- these are allowed withing a path segment, along with alphanum
+-- other characters must be escaped
+local segment_set = make_set {
+ "-", "_", ".", "!", "~", "*", "'", "(",
+ ")", ":", "@", "&", "=", "+", "$", ",",
+}
+
+local function protect_segment(s)
+ return string.gsub(s, "([^A-Za-z0-9_])", function (c)
+ if segment_set[c] then return c
+ else return string.format("%%%02x", string.byte(c)) end
+ end)
+end
+
+-----------------------------------------------------------------------------
+-- Encodes a string into its escaped hexadecimal representation
+-- Input
+-- s: binary string to be encoded
+-- Returns
+-- escaped representation of string binary
+-----------------------------------------------------------------------------
+function unescape(s)
+ return string.gsub(s, "%%(%x%x)", function(hex)
+ return string.char(base.tonumber(hex, 16))
+ end)
+end
+
+-----------------------------------------------------------------------------
+-- Builds a path from a base path and a relative path
+-- Input
+-- base_path
+-- relative_path
+-- Returns
+-- corresponding absolute path
+-----------------------------------------------------------------------------
+local function absolute_path(base_path, relative_path)
+ if string.sub(relative_path, 1, 1) == "/" then return relative_path end
+ local path = string.gsub(base_path, "[^/]*$", "")
+ path = path .. relative_path
+ path = string.gsub(path, "([^/]*%./)", function (s)
+ if s ~= "./" then return s else return "" end
+ end)
+ path = string.gsub(path, "/%.$", "/")
+ local reduced
+ while reduced ~= path do
+ reduced = path
+ path = string.gsub(reduced, "([^/]*/%.%./)", function (s)
+ if s ~= "../../" then return "" else return s end
+ end)
+ end
+ path = string.gsub(reduced, "([^/]*/%.%.)$", function (s)
+ if s ~= "../.." then return "" else return s end
+ end)
+ return path
+end
+
+-----------------------------------------------------------------------------
+-- Parses a url and returns a table with all its parts according to RFC 2396
+-- The following grammar describes the names given to the URL parts
+-- <url> ::= <scheme>://<authority>/<path>;<params>?<query>#<fragment>
+-- <authority> ::= <userinfo>@<host>:<port>
+-- <userinfo> ::= <user>[:<password>]
+-- <path> :: = {<segment>/}<segment>
+-- Input
+-- url: uniform resource locator of request
+-- default: table with default values for each field
+-- Returns
+-- table with the following fields, where RFC naming conventions have
+-- been preserved:
+-- scheme, authority, userinfo, user, password, host, port,
+-- path, params, query, fragment
+-- Obs:
+-- the leading '/' in {/<path>} is considered part of <path>
+-----------------------------------------------------------------------------
+function parse(url, default)
+ -- initialize default parameters
+ local parsed = {}
+ for i,v in base.pairs(default or parsed) do parsed[i] = v end
+ -- empty url is parsed to nil
+ if not url or url == "" then return nil, "invalid url" end
+ -- remove whitespace
+ -- url = string.gsub(url, "%s", "")
+ -- get fragment
+ url = string.gsub(url, "#(.*)$", function(f)
+ parsed.fragment = f
+ return ""
+ end)
+ -- get scheme
+ url = string.gsub(url, "^([%w][%w%+%-%.]*)%:",
+ function(s) parsed.scheme = s; return "" end)
+ -- get authority
+ url = string.gsub(url, "^//([^/]*)", function(n)
+ parsed.authority = n
+ return ""
+ end)
+ -- get query stringing
+ url = string.gsub(url, "%?(.*)", function(q)
+ parsed.query = q
+ return ""
+ end)
+ -- get params
+ url = string.gsub(url, "%;(.*)", function(p)
+ parsed.params = p
+ return ""
+ end)
+ -- path is whatever was left
+ if url ~= "" then parsed.path = url end
+ local authority = parsed.authority
+ if not authority then return parsed end
+ authority = string.gsub(authority,"^([^@]*)@",
+ function(u) parsed.userinfo = u; return "" end)
+ authority = string.gsub(authority, ":([^:]*)$",
+ function(p) parsed.port = p; return "" end)
+ if authority ~= "" then parsed.host = authority end
+ local userinfo = parsed.userinfo
+ if not userinfo then return parsed end
+ userinfo = string.gsub(userinfo, ":([^:]*)$",
+ function(p) parsed.password = p; return "" end)
+ parsed.user = userinfo
+ return parsed
+end
+
+-----------------------------------------------------------------------------
+-- Rebuilds a parsed URL from its components.
+-- Components are protected if any reserved or unallowed characters are found
+-- Input
+-- parsed: parsed URL, as returned by parse
+-- Returns
+-- a stringing with the corresponding URL
+-----------------------------------------------------------------------------
+function build(parsed)
+ local ppath = parse_path(parsed.path or "")
+ local url = build_path(ppath)
+ if parsed.params then url = url .. ";" .. parsed.params end
+ if parsed.query then url = url .. "?" .. parsed.query end
+ local authority = parsed.authority
+ if parsed.host then
+ authority = parsed.host
+ if parsed.port then authority = authority .. ":" .. parsed.port end
+ local userinfo = parsed.userinfo
+ if parsed.user then
+ userinfo = parsed.user
+ if parsed.password then
+ userinfo = userinfo .. ":" .. parsed.password
+ end
+ end
+ if userinfo then authority = userinfo .. "@" .. authority end
+ end
+ if authority then url = "//" .. authority .. url end
+ if parsed.scheme then url = parsed.scheme .. ":" .. url end
+ if parsed.fragment then url = url .. "#" .. parsed.fragment end
+ -- url = string.gsub(url, "%s", "")
+ return url
+end
+
+-----------------------------------------------------------------------------
+-- Builds a absolute URL from a base and a relative URL according to RFC 2396
+-- Input
+-- base_url
+-- relative_url
+-- Returns
+-- corresponding absolute url
+-----------------------------------------------------------------------------
+function absolute(base_url, relative_url)
+ if base.type(base_url) == "table" then
+ base_parsed = base_url
+ base_url = build(base_parsed)
+ else
+ base_parsed = parse(base_url)
+ end
+ local relative_parsed = parse(relative_url)
+ if not base_parsed then return relative_url
+ elseif not relative_parsed then return base_url
+ elseif relative_parsed.scheme then return relative_url
+ else
+ relative_parsed.scheme = base_parsed.scheme
+ if not relative_parsed.authority then
+ relative_parsed.authority = base_parsed.authority
+ if not relative_parsed.path then
+ relative_parsed.path = base_parsed.path
+ if not relative_parsed.params then
+ relative_parsed.params = base_parsed.params
+ if not relative_parsed.query then
+ relative_parsed.query = base_parsed.query
+ end
+ end
+ else
+ relative_parsed.path = absolute_path(base_parsed.path or "",
+ relative_parsed.path)
+ end
+ end
+ return build(relative_parsed)
+ end
+end
+
+-----------------------------------------------------------------------------
+-- Breaks a path into its segments, unescaping the segments
+-- Input
+-- path
+-- Returns
+-- segment: a table with one entry per segment
+-----------------------------------------------------------------------------
+function parse_path(path)
+ local parsed = {}
+ path = path or ""
+ --path = string.gsub(path, "%s", "")
+ string.gsub(path, "([^/]+)", function (s) table.insert(parsed, s) end)
+ for i = 1, table.getn(parsed) do
+ parsed[i] = unescape(parsed[i])
+ end
+ if string.sub(path, 1, 1) == "/" then parsed.is_absolute = 1 end
+ if string.sub(path, -1, -1) == "/" then parsed.is_directory = 1 end
+ return parsed
+end
+
+-----------------------------------------------------------------------------
+-- Builds a path component from its segments, escaping protected characters.
+-- Input
+-- parsed: path segments
+-- unsafe: if true, segments are not protected before path is built
+-- Returns
+-- path: corresponding path stringing
+-----------------------------------------------------------------------------
+function build_path(parsed, unsafe)
+ local path = ""
+ local n = table.getn(parsed)
+ if unsafe then
+ for i = 1, n-1 do
+ path = path .. parsed[i]
+ path = path .. "/"
+ end
+ if n > 0 then
+ path = path .. parsed[n]
+ if parsed.is_directory then path = path .. "/" end
+ end
+ else
+ for i = 1, n-1 do
+ path = path .. protect_segment(parsed[i])
+ path = path .. "/"
+ end
+ if n > 0 then
+ path = path .. protect_segment(parsed[n])
+ if parsed.is_directory then path = path .. "/" end
+ end
+ end
+ if parsed.is_absolute then path = "/" .. path end
+ return path
+end
diff --git a/lib/support/socket.lua b/lib/support/socket.lua
new file mode 100644
index 0000000..211adcd
--- /dev/null
+++ b/lib/support/socket.lua
@@ -0,0 +1,133 @@
+-----------------------------------------------------------------------------
+-- LuaSocket helper module
+-- Author: Diego Nehab
+-- RCS ID: $Id: socket.lua,v 1.22 2005/11/22 08:33:29 diego Exp $
+-----------------------------------------------------------------------------
+
+-----------------------------------------------------------------------------
+-- Declare module and import dependencies
+-----------------------------------------------------------------------------
+local base = _G
+local string = require("string")
+local math = require("math")
+local socket = require("socket.core")
+module("socket")
+
+-----------------------------------------------------------------------------
+-- Exported auxiliar functions
+-----------------------------------------------------------------------------
+function connect(address, port, laddress, lport)
+ local sock, err = socket.tcp()
+ if not sock then return nil, err end
+ if laddress then
+ local res, err = sock:bind(laddress, lport, -1)
+ if not res then return nil, err end
+ end
+ local res, err = sock:connect(address, port)
+ if not res then return nil, err end
+ return sock
+end
+
+function bind(host, port, backlog)
+ local sock, err = socket.tcp()
+ if not sock then return nil, err end
+ sock:setoption("reuseaddr", true)
+ local res, err = sock:bind(host, port)
+ if not res then return nil, err end
+ res, err = sock:listen(backlog)
+ if not res then return nil, err end
+ return sock
+end
+
+try = newtry()
+
+function choose(table)
+ return function(name, opt1, opt2)
+ if base.type(name) ~= "string" then
+ name, opt1, opt2 = "default", name, opt1
+ end
+ local f = table[name or "nil"]
+ if not f then base.error("unknown key (".. base.tostring(name) ..")", 3)
+ else return f(opt1, opt2) end
+ end
+end
+
+-----------------------------------------------------------------------------
+-- Socket sources and sinks, conforming to LTN12
+-----------------------------------------------------------------------------
+-- create namespaces inside LuaSocket namespace
+sourcet = {}
+sinkt = {}
+
+BLOCKSIZE = 2048
+
+sinkt["close-when-done"] = function(sock)
+ return base.setmetatable({
+ getfd = function() return sock:getfd() end,
+ dirty = function() return sock:dirty() end
+ }, {
+ __call = function(self, chunk, err)
+ if not chunk then
+ sock:close()
+ return 1
+ else return sock:send(chunk) end
+ end
+ })
+end
+
+sinkt["keep-open"] = function(sock)
+ return base.setmetatable({
+ getfd = function() return sock:getfd() end,
+ dirty = function() return sock:dirty() end
+ }, {
+ __call = function(self, chunk, err)
+ if chunk then return sock:send(chunk)
+ else return 1 end
+ end
+ })
+end
+
+sinkt["default"] = sinkt["keep-open"]
+
+sink = choose(sinkt)
+
+sourcet["by-length"] = function(sock, length)
+ return base.setmetatable({
+ getfd = function() return sock:getfd() end,
+ dirty = function() return sock:dirty() end
+ }, {
+ __call = function()
+ if length <= 0 then return nil end
+ local size = math.min(socket.BLOCKSIZE, length)
+ local chunk, err = sock:receive(size)
+ if err then return nil, err end
+ length = length - string.len(chunk)
+ return chunk
+ end
+ })
+end
+
+sourcet["until-closed"] = function(sock)
+ local done
+ return base.setmetatable({
+ getfd = function() return sock:getfd() end,
+ dirty = function() return sock:dirty() end
+ }, {
+ __call = function()
+ if done then return nil end
+ local chunk, err, partial = sock:receive(socket.BLOCKSIZE)
+ if not err then return chunk
+ elseif err == "closed" then
+ sock:close()
+ done = 1
+ return partial
+ else return nil, err end
+ end
+ })
+end
+
+
+sourcet["default"] = sourcet["until-closed"]
+
+source = choose(sourcet)
+
diff --git a/lib/support/socket/core.so b/lib/support/socket/core.so
new file mode 100755
index 0000000..ddfc8c3
--- /dev/null
+++ b/lib/support/socket/core.so
Binary files differ