O script abaixo foi modificado a partir do original que se encontra em .... A biblioteca(librarie) gpio.lua, obtida no mesmo site, foi alterada em suas entranhas para funcionar corretamente no nosso Roteador Turbinado. Quem não sabe o que é Lua e para aqueles que perderam o Eclipse da Lua Vermelha, recomendamos visitar o site www.lua.org.
Quem ganha a vida programando e desenvolvendo sistemas com inúmeras linhas de código, obedecendo as melhores práticas da indústria de software, provavelmente deve ter sua linguagem de programação favorita e chegar ao ponto de discutir em fóruns espalhados na internet sobre as vantagens de sua linguagem e das desvantagens da dos outros.
O Solucionática não tem tempo e nem conhecimento para discutir esse assunto.Se para resolver um problema for preciso usar uma ou outra linguagem de programação não hesitaremos, pois nossos princípios mais elementares preconizam a simplicidade (exceto nesse parágrafo) e a funcionalidade.
Lua é uma linguagem de programação muito boa, ideal para sistemas embarcados. Uma pena não termos conhecido há mais tempo. E ainda por cima foi criada no Brasil por professores brasileiros da PUC Rio. Depois de Python nunca pensamos em nos deparar com algo tão poderoso, leve e sem excesso de formalismo. Vale à pena usar nosso método de aprendizagem, o famoso Ctrl+c, Ctrl+v. E qual será nosso objetivo? A meta é usar um script Lua para acender os quatro leds configuráveis do roteador TL-MR3020. Lua já vem instalada, como na maior parte das distros Linux.
Vamos ao programa:
--turn on/off leds
require ("gpio")
local leds = {}
leds[1]='lan'
leds[2]='wps'
leds[3]='3g
leds[4]='wlan'
for i,v in ipairs(leds) do
--configure v as output gpio
configureOutGPIO(v)
end
while true do
for i,v in ipairs(leds) do
writeGPIO(leds[i],1)
sleep(1)
writeGPIO(leds[i],0)
end
end
while true do
writeGPIO(leds[i],1)
sleep(1)
writeGPIO(leds[i],0)
end
Para aqueles familiarizados com Python entender o código é uma tarefa bem simples. Mas, mesmo os mais avançados especialistas em linguagens de programação, tem dificuldade em adaptar o script de acordo com as características de hardware do MR3020.
Boa parte da complexidade desse projeto reside em conhecer os detalhes do hardware e adaptar a bilioteca gpio.lua. Vamos aos detalhes:
--@author: Ewelina, Rafa, Rafa
--GPIO utilities
--Writes 'what' to 'where'
function writeToFile (where,what)
local fileToWrite=io.open(where, 'w')
fileToWrite:write(what)
fileToWrite:close()
end
--Reads a character from file 'where' and returns the string
function readFromFile (where)
local fileToRead=io.open(where, 'r')
fileStr = fileToRead:read(1)
fileToRead:close()
return fileStr
end
--Returns true if file exists
function file_exists(name)
local f=io.open(name,"r")
if f~=nil then io.close(f) return true else return false end
end
--Exports gpio ID to use as an output pin
function configureOutGPIO (id)
if not file_exists('/sys/class/gpio/gpio'..id..'/direction') then
writeToFile('/sys/class/gpio/export',id)
end
writeToFile('/sys/class/gpio/gpio'..id..'/direction','out')
end
--Exports gpio ID to use as an input pin
function configureInGPIO (id)
if not file_exists('/sys/class/gpio/gpio'..id..'/direction') then
writeToFile('/sys/class/gpio/export',id)
end
writeToFile('/sys/class/gpio/gpio'..id..'/direction','in')
end
--Reads GPIO 'id' and returns it's value
--@Pre: GPIO 'id' must be exported with configureInGPIO
function readGPIO(id)
gpioVal = readFromFile('/sys/class/gpio/gpio'..id..'/value')
return gpioVal
end
--Writes a value to GPIO 'id'
--@Pre: GPIO 'id' must be exported with configureOutGPIO
function writeGPIO(id, val)
gpioVal = writeToFile('/sys/class/gpio/gpio'..id..'/value', val)
end
function sleep(n)
os.execute("sleep " .. tonumber(n))
end
Script para ler o status da chave seletora do roteador
--teste
local t={}
local line
local len=1
for line in io.lines('/sys/kernel/debug/gpio') do
t[len]=line
len=len+1
end
local gpio18=t[6]
local sw1=string.find(gpio18,'hi',1,true)
if type(sw1)=="number" then
print("Gpio 18 hi")
else print("gpio 18 low")
end
Explicação:
t é uma table
io.lines(arquivo) é um iterador. Ele conta o número de linhas do arquivo e controla o loop for de preenchimento da tabela t.
A indexação da linha a uma posição na tabela é feita em função de len, uma variável simples incrementada a cada passo do loop for.
Line é uma variável que armazena cada uma das linhas do arquivo que preencherão a tabela da linha 1 até o número máximo de linhas dada por io.lines('/sys/kernel/debug/gpio')
gpio18=t[6] é uma variável auxiliar que assume o valor contido na linha 6 do arquivo (/sys/kernel/debug/gpio).
sw1 é uma variável que armazena o resultado do teste: há a substring 'hi' na linha 6?
if type(sw1) testa o tipo da variável. Espera-se que seja um número (se sw1 for hi), pois é a posição do último caractere da substring dentro da string gpio18(o 38° caractere dessa string é um 'i').
Quando gpio-18 é lo (low) o valor de retorno é nil, ou seja não é número. Nil é um tipo particular em Lua, que significa variável não inicializada.
Resumo: quando existe a coincidência sw1=posição do último caractere, caso contrário sw1=nil.
Para fechar o programa , há uma condição de teste que imprime o valor de gpio-18 (HI ou LOW).
To do: acrescentar o teste para gpio-20 que está na linha 7 da tabela. E determinar o estado da chave (3g, Wisp ou AP). Esse estado é na verdade irrelevante, pois o roteador modificado não faz uso dessa chave, mas pode ser aproveitada para determinar uma outra configuração ou executar um script, por exemplo.
O script pode ser modificado para facilmente efetuar a leitura de toda GPIO, inclusive aquelas que ainda não foram exportadas, ou seja, não aparecem na listagem ao executar ># cat /sys/kernel/debug/gpio:
root@ROOter:~# cat /sys/kernel/debug/gpio
GPIOs 0-29, ath79:
gpio-0 (tp-link:green:wlan ) out hi
gpio-8 (USB power ) out hi
gpio-11 (wps ) in lo
gpio-17 (tp-link:green:lan ) out hi
gpio-18 (sw1 ) in hi
gpio-20 (sw2 ) in hi
gpio-26 (tp-link:green:wps ) out lo
gpio-27 (tp-link:green:3g ) out hi
Script com modificação para imprimir o conteúdo do arquivo após checar o status da chave (GPIO18).
Ver isso: http://ediy.com.my/projects/item/99-wireless-router-remote-control-car
Lua TP-Link MR3020 RSSI Strenght Meter
--rssi
-- ID AF home 4c:17:eb:de:7e:a3
-- ID Af mobile f0:d7:aa:e8:9c:0e
require ("gpio")
local leds = {}
leds[1]='3g'
leds[2]='wlan'
leds[3]='lan'
leds[4]='wps'
while 1 do
local t={}
local line
local len=1
--for line in io.lines('/proc/net/wireless') do
for line in io.lines('/sys/kernel/debug/ieee80211/phy0/netdev:wlan0/stations/4c:17:eb:de:7e:a3/last_signal') do
t[len]=line
len=len+1
end
writeGPIO(leds[1],0)
writeGPIO(leds[2],0)
writeGPIO(leds[3],0)
writeGPIO(leds[4],0)
local gpio18=t[1]
local sw1=string.find(gpio18,'-',1,true)
s=t[1]
--while 1 do
RSSI=tonumber(string.sub(s,2,3))
if RSSI ==0 then print("wifi nao conectado")
elseif RSSI>0 and RSSI<=25 then
print("RSSI EXCELENTE")
writeGPIO(leds[1],1)
writeGPIO(leds[2],1)
writeGPIO(leds[3],1)
writeGPIO(leds[4],1)
elseif RSSI >25 and RSSI <40 then
print("RSSI BOM")
writeGPIO(leds[1],1)
writeGPIO(leds[2],1)
writeGPIO(leds[3],1)
writeGPIO(leds[4],0)
elseif RSSI >=40 and RSSI <55 then
print ("RSSI FRACO")
writeGPIO(leds[1],1)
writeGPIO(leds[2],1)
writeGPIO(leds[3],0)
writeGPIO(leds[4],0)
elseif RSSI >=55 and RSSI <70 then
print ("RSSI MUITO FRACO")
writeGPIO(leds[1],1)
writeGPIO(leds[2],0)
writeGPIO(leds[3],0)
writeGPIO(leds[4],0)
elseif RSSI >=70 then
print ("RSSI RUIM")
writeGPIO(leds[1],0)
writeGPIO(leds[2],0)
writeGPIO(leds[3],0)
writeGPIO(leds[4],0)
end
print("RSSI= -",RSSI)
--io.write("RSSI= -\n ",RSSI)
--io.flush()
--print (t[21])
--print (sw1)
--print (s)
--if type(sw1)=="number" then
-- print("Gpio 18 -")
-- else print("gpio 18 low")
--end
end
Outra forma de fazer o controle dos leds:
#!/usr/bin/lua
-- a lua library for sending data to 74HC595 Shift Registers
-- by http://ediy.com.my
require "gpio" -- Lua library to allow access to the GPIO
require "bit" -- Bitfield operators and manipulation functions
--require "shiftOut2"
---------- global variables
LatchPin = 'wlan' --or LatchPin=GPIO[1] (refer gpio.lua global variables)
DataPin = 'lan' --or DataPin=GPIO[2]
ClockPin = 'wps' --or ClockPin=GPIO[3]
OutputEnablePin = '3g' --or OutputEnablePin=GPIO[4]
Number_of_bit = 8 --use 16 for two 74HC595, 24 for three 74HC595, etc...
LSBFIRST = 1
MSBFIRST = 0
---------- configures the specified pin to behave as an output
--pinMode(LatchPin, OUTPUT)
--pinMode(DataPin, OUTPUT)
--pinMode(ClockPin, OUTPUT)
--pinMode(OutputEnablePin, OUTPUT)
---------- shiftOut function (sending data to 74HC595)
function shiftOut(dataPin, clockPin, bitOrder, val)
for i = 0, Number_of_bit-1 do
if bitOrder==MSBFIRST then
bitToSend=nixio.bit.band(val,nixio.bit.lshift(1,Number_of_bit-1-i))
else
bitToSend=nixio.bit.band(val,nixio.bit.lshift(1,i))
end
if bitToSend~=0 then bitToSend=1 end --convert non zero to 1
writeGPIO(DataPin, bitToSend)
writeGPIO(ClockPin, 1)
writeGPIO(ClockPin, 0)
end
end
---------- binary to decimal number conversion
function binary_to_decimal(str)
local result = 0
local power=1
for i = #str, 1, -1 do
local c = str:sub(i,i)
local i=tonumber(c)
result = result+ i*power
power=power*2
end
return(result)
end
---------- update Shift Register (decimal number)
function update_ShiftRegister(value, bitOrder)
writeGPIO(LatchPin,0) -- write LOW(0) to the LatchPin
shiftOut(DataPin, ClockPin, bitOrder, value)
writeGPIO(LatchPin,1) -- write HIGH(1) to the LatchPin
end
---------- update Shift Register (binary number)
function update_ShiftRegister_Binary(binary_number, bitOrder)
local value = binary_to_decimal(binary_number)
update_ShiftRegister(value, bitOrder)
end
Usa esse outro arquivo: sleep2.lua
function sleep2(s)
local ntime = os.time() + s
repeat until os.time() > ntime
end
Programa principal:
!/usr/bin/lua
require "gpio"
require "shiftOut2"
require "bit"
require "nixio"
require "sleep2"
--require "gpiobit"
print("===== LSBFIRST =====")
for i= 0, Number_of_bit do
value=nixio.bit.lshift(1,i)
print("update_ShiftRegister("..value..",LSBFIRST)")
update_ShiftRegister(value,LSBFIRST)
sleep2(0.2)
end
print("===== MSBFIRST =====")
for i= 0, Number_of_bit do
value=nixio.bit.lshift(1,i)
print("update_ShiftRegister("..value..",MSBFIRST)")
update_ShiftRegister(value,MSBFIRST)
sleep2(0.2)
end
print("===== LSBFIRST =====")
for i= 0, Number_of_bit do
value=nixio.bit.lshift(1,i)-1
print("update_ShiftRegister("..value..",LSBFIRST)")
update_ShiftRegister(value,LSBFIRST)
sleep2(0.2)
end
print("===== MSBFIRST =====")
for i= 0, Number_of_bit do
value=nixio.bit.lshift(1,i)-1
print("update_ShiftRegister("..value..",MSBFIRST)")
update_ShiftRegister(value,MSBFIRST)
sleep2(0.2)
end
print("===== ALL OFF =====")
value=0
print("update_ShiftRegister("..value..",LSBFIRST)")
update_ShiftRegister(value,LSBFIRST)
PORTA SERIAL
https://stackoverflow.com/questions/15701694/lua-io-read-sends-me-an-echo-back-when-i-read-from-serial-port-why
http://www.hackinglab.org/lua/luasource.html
Lua Chat Server/Client:
Client:
require('socket') -- sempre o require
local client = socket.connect('192.168.1.2',1234)
if client then
print('Conectado')
else
print('offline')
os.exit()
end
print('Escreva algo')
repeat
local m = io.read()
if m ~= '' then
client:send(m..'\n')
end
client:settimeout(0.1)
local msg,stat = client:receive()
if msg then
print(msg)
end
until not client
Server:
require('socket') -- sempre o require
local host = socket.bind('192.168.1.2',1234)
print('Aguardando uma conexao!')
local user = host:accept()
print('Alguem se conectou! aguardando dados')
while true do
local mensagem, status = user:receive()
if status == 'closed' then
break
end
print(mensagem)
end