Перший код в LUA. Скрипт для роутера з OpenWRT. MQTT та Telegram статус підключених WiFi clients.
З метою оптимізації мого попереднього коду (Нотатки : Простий скрипт для wifi device tracker в OpenWRT : відсилання повідомлень до MQTT ) в SHELL script так як його можливості дещо обмежені. Перевів код на LUA - швидка і компактна скриптова мова програмування.
Мета коду - зробити автоматизацію вдома на основі присутності людей. Один з варіантів визначення присутності це за тим чи підключений мобільний телефон особи до домашньої Wi-Fi мережі.

Результати роботи визначення статусу в телеграм групі
Так як мобільний телефон при підключенні до мережі Wi-Fi використовує унікальні MAC адреси, то за активністю MAC адрес можна припустити по наявність особи вдома.
iwinfo
Прилад роботи команди в роутері: iwinfo
$ iwinfo wlan0 assoclist
AA:AA:AA:AA:AA:E6 -47 dBm / -93 dBm (SNR 46) 1860 ms ago
RX: 6.0 MBit/s 47653 Pkts.
TX: 72.2 MBit/s, MCS 7, 20MHz 877 Pkts.
expected throughput: 34.9 MBit/s
AA:AA:AA:AA:D3:12 -66 dBm / -93 dBm (SNR 27) 3224 ms ago
RX: 6.0 MBit/s 7281 Pkts.
TX: 120.0 MBit/s, MCS 5, 40MHz 1461 Pkts.
expected throughput: 39.1 MBit/s
AA:AA:AA:AA:58:39 -68 dBm / -93 dBm (SNR 25) 25836 ms ago
RX: 24.0 MBit/s 8812 Pkts.
TX: 65.0 MBit/s, MCS 6, 20MHz 3922 Pkts.
expected throughput: 27.9 MBit/s
AA:AA:AA:AA:34:77 -43 dBm / -93 dBm (SNR 50) 9316 ms ago
RX: 6.0 MBit/s 3420 Pkts.
TX: 72.2 MBit/s, MCS 7, 20MHz 1050 Pkts.
expected throughput: 34.9 MBit/s
В результаті вибираємо тарі параметри як “MAC” адреса, так час останньої активності “AGO”.
За допомогою awk дещо фільтруємо результат виведення MAC, наприклад якщо активність була менша за останні 50 сек.
iwinfo wlan0 assoclist|awk '{if (($11) && ($9<50000)) print $1}'
AA:AA:AA:AA:AA:E6
AA:AA:AA:AA:D3:12
AA:AA:AA:AA:58:39
AA:AA:AA:AA:34:77
Тепер до скрипту в LUA - device-tracker.lua:
#!/usr/bin/lua
local os=require("os")
users = {
["user1"] = 'AA:AA:AA:AA:34:77',
["user2"] = 'AA:AA:AA:AA:58:39'
}
ustate = {}
next = false
local function sleep(n)
os.execute("sleep " .. tonumber(n))
end
local function publish (topic, mess)
os.execute("mosquitto_pub -t '" .. topic .. "' -m '" .. mess .. "' -r -q 2" )
end
-- main code
sleep(120)
-- initialize previos users state tabe
for u,m in pairs(users) do
ustate[u] = 0
end
while true do
-- get list of active wifi mac addresess
local us=io.popen( "iwinfo wlan0 assoclist|awk '{if (($11) && ($9<50000)) print $1}'" )
maclist = {}
for line in us:lines() do
maclist[line]=true;
end
us:close()
for u,m in pairs(users) do
result = maclist[m] and 1 or 0
if ustate[u] ~= result then
ustate[u]=result
if next then
-- print( "state user :" .. u .. " changed" )
publish("tele/wifi_" .. u .. "/LWT",result)
end
end
end
next=true
sleep(5)
end
libiwinfo-lua
Якщо встановити пакунок OpenWRT - libiwinfo-lua : opkg install libiwinfo-lua, то необхідність запуску зовнішніх програм для визначення активних wifi клієнтів відпадає.
#!/usr/bin/lua
local os=require("os")
-- opkg install libiwinfo-lua
local iwinfo=require("iwinfo")
-- MAC DataBase of users
local users = {
["user1"] = 'AA:AA:AA:AA:34:77',
["user2"] = 'AA:AA:AA:AA:58:39'
}
-- LIST of WiFi APs, 2.4GHz, 5GHz
local ifaces = {"wlan0"}
-- FUNCTIONS
local function sleep(n)
os.execute("sleep " .. tonumber(n))
end
local function publish (topic, mess)
os.execute("mosquitto_pub -t '" .. topic .. "' -m '" .. mess .. "' -r -q 2" )
end
-- MAIN CODE
local ustate = {}
local next = false
-- initialize previos users state tabe
for u,m in pairs(users) do
ustate[u] = 0
end
-- list of wifi clients
local maxInactive = 70000
while true do
-- get list of active wifi mac addresess
local maclist = {}
for _,iface in pairs(ifaces) do
local ifacet = iwinfo.type(iface)
local clients = iwinfo[ifacet].assoclist(iface)
for mac,v in pairs(clients) do
if v.inactive < maxInactive then
-- print(iface, mac, v.inactive)
maclist[mac]=true
end
end
end
for u,m in pairs(users) do
local result = maclist[m] and 1 or 0
if ustate[u] ~= result then
ustate[u]=result
if next then
-- print( "state user: " .. u .. " changed: " .. result )
publish("tele/wifi_" .. u .. "/LWT",result)
end
end
end
next=true
sleep(5)
end
autorun
Скрипт автоматично завантажується при запуску системи.

Автоматичний запуск скрипту device-tracker.lua в OpenWRT
mqtt
Результат роботи є запуск команди: mosquitto_pub, яка публікує повідомлення до MQTT брокера.
В даному випадку mqtt брокер mosquitto встановлений в цьому роутері.
Скрипт який відсилає повідомлення то Telegam було описано мною раніше: “Нотатки : Простий скрипт для MQTT в OpenWRT : відсилання Telegram повідомлень з Emoji. Tasmota. “
lua-mosquitto
Якщо встановити пакунок OpenWRT - lua-mosquitto : opkg install lua-mosquitto, функцію publish можна переписати так:
-- opkg install lua-mosquitto
local mqtt = require("mosquitto")
local function publish(t,m)
client = mqtt.new()
client.ON_CONNECT = function()
client:publish(t,m,2,true)
end
client.ON_PUBLISH = function()
client:disconnect()
end
client:connect()
client:loop_forever()
end
Але розмір використаної оперативної пам’яті збільшиться в 2.4 рази, тому, я вважаю що недоцільно використовувати lua-mosquitto для одноразового використання, краще запустити зовнішню програму mosquitto_pub.
Оптимізація sleep
-- opkg install luasocket
local socket = require 'socket'
local function sleep(n)
socket.sleep(tonumber(n))
-- os.execute("sleep " .. tonumber(n))
end
Розмір став 1916, але не має процесу sleep котрий займає 1250.
