З метою оптимізації мого попереднього коду (Нотатки : Простий скрипт для 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.