Giter VIP home page Giter VIP logo

barbieri-playground's Introduction

Code Playground
===============

This area is to keep code I write but isn't part of a project.


COPYING / LICENSE
=================

Code present here is under GNU GPL unless a different license is stated.


AUTHOR
======

Gustavo Sverzut Barbieri <barbieri at gmail.com>

barbieri-playground's People

Contributors

barbieri avatar papaulogamerofc avatar petzah avatar schmidtw avatar seemebreakthis avatar tomeon avatar twijit avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

barbieri-playground's Issues

802.11S ??? WORK?

I tried your scrypt and it works visually but the STAs really don't get disconnected as ever?

The test was performed in MESH 802.11S mode

wifi-disconnect-low-signal: wlan0: 90:F6:52:40:03:8E signal=-68dBm snr=26dBm strikes=3 (threshold: snr_stay=27 strikes=3): should disconnect
wifi-disconnect-low-signal: wlan0: disconnected 90:F6:52:40:03:8E {signal=-68dBm, noise=-94dBm, snr=26dBm, strikes=3, is_new=false}
wifi-disconnect-low-signal: wlan0: signal poll: 1 STAs, 1 disconnected
wifi-disconnect-low-signal: wlan0: signal poll: 0 STAs, 0 disconnected
wifi-disconnect-low-signal: wlan0: signal poll: 0 STAs, 0 disconnected
wifi-disconnect-low-signal: wlan0: signal poll: 0 STAs, 0 disconnected
wifi-disconnect-low-signal: wlan0: signal poll: 0 STAs, 0 disconnected
wifi-disconnect-low-signal: wlan0: signal poll: 0 STAs, 0 disconnected
wifi-disconnect-low-signal: wlan0: signal poll: 0 STAs, 0 disconnected
wifi-disconnect-low-signal: wlan0: signal poll: 0 STAs, 0 disconnected
wifi-disconnect-low-signal: wlan0: signal poll: 0 STAs, 0 disconnected
wifi-disconnect-low-signal: wlan0: signal poll: 0 STAs, 0 disconnected
wifi-disconnect-low-signal: wlan0: signal poll: 0 STAs, 0 disconnected
wifi-disconnect-low-signal: wlan0: signal poll: 0 STAs, 0 disconnected
wifi-disconnect-low-signal: wlan0: signal poll: 0 STAs, 0 disconnected
wifi-disconnect-low-signal: wlan0: forget 90:F6:52:40:03:8E
wifi-disconnect-low-signal: wlan0: 90:F6:52:40:03:8E signal=-55dBm snr=40dBm strikes=0 (threshold: snr_connect=33 strikes=0): good signal
wifi-disconnect-low-signal: wlan0: signal poll: 1 STAs, 0 disconnected
wifi-disconnect-low-signal: wlan0: 90:F6:52:40:03:8E signal=-43dBm snr=52dBm strikes=0 (threshold: snr_stay=27 strikes=3): good signal
wifi-disconnect-low-signal: wlan0: signal poll: 1 STAs, 0 disconnected
wifi-disconnect-low-signal: wlan0: 90:F6:52:40:03:8E signal=-42dBm snr=53dBm strikes=0 (threshold: snr_stay=27 strikes=3): good signal
wifi-disconnect-low-signal: wlan0: signal poll: 1 STAs, 0 disconnected
wifi-disconnect-low-signal: wlan0: 90:F6:52:40:03:8E signal=-42dBm snr=53dBm strikes=0 (threshold: snr_stay=27 strikes=3): good signal
wifi-disconnect-low-signal: wlan0: signal poll: 1 STAs, 0 disconnected

wifi disconnect config interpretation

Hello.

I was playing with your wifi-disconnect, and I while I got it working, I do have to report some suggestions. Please note that this does not lessen my appreciation for writing and publishing the tool.
ALso, I am always open to the suggestion I am simply using it wrong, in which case my appologies.

I have 4 items, listed below

  1. It is unable to read the wifi-iface section if those sections are not named.
    My Luci generates, and also the OpenWRT wiki does not show allowance for labels for the wifi-iface section headers.
    Your example does show them. It turns out if these labels are not present, your script is not able to interpret the values:

So this works

config wifi-iface 'default_radio0'
	option device 'radio0'
	option mode 'ap'
	option network 'lan'
	option ssid 'my-wifi'
	option key 'my-passwd'
	option encryption 'psk2+ccmp'
	option signal_snr_connect '25'
	option signal_snr_stay '20'
	option signal_strikes '3'
	option signal_poll_time '5'
	option signal_drop_reason '3'

But this is how a normal generated section looks, and it does not work with your script:
(to be quite honest, I am not even sure what the 'default_radio0' in your example above is supposed to do, as it is not described in OpenWRT WiKi

config wifi-iface
	option device 'radio0'
	option mode 'ap'
	option network 'lan'
	option ssid 'my-wifi'
	option key 'my-passwd'
	option encryption 'psk2+ccmp'
	option signal_snr_connect '25'
	option signal_snr_stay '20'
	option signal_strikes '3'
	option signal_poll_time '5'
	option signal_drop_reason '3'
  1. When it starts running, it seems that even though "strikes=3" is set, it at first uses value "strikes=0"
root@W115_Spare:/tmp# lua wifi-disconnect-low-signal.lua -v -v --stderr
wifi-disconnect-low-signal: radio0: wlan0 {signal_connect=-20dBm, signal_stay=-30dBm, poll_time=5s, strikes=3, drop_reason=3}
wifi-disconnect-low-signal: radio0: wlan0-1 {signal_connect=-20dBm, signal_stay=-30dBm, poll_time=5s, **_strikes=3_**, drop_reason=3}
wifi-disconnect-low-signal: found 2 enabled WiFi devices
wifi-disconnect-low-signal: wlan0: 00:27:22:76:1A:47 signal=-42dBm snr=53dBm strikes=1 (threshold: signal_connect=-20 **_strikes=0_**): should disconnect
wifi-disconnect-low-signal: wlan0: disconnected 00:27:22:76:1A:47 {signal=-42dBm, noise=-95dBm, snr=53dBm, strikes=1, is_new=true}
wifi-disconnect-low-signal: wlan0: signal poll: 1 STAs, 1 disconnected
wifi-disconnect-low-signal: wlan0-1: no associated STAs
wifi-disconnect-low-signal: wlan0: signal poll: 0 STAs, 0 disconnected
root@W115_Spare:/tmp# lua wifi-disconnect-low-signal.lua -v -v --stderr
wifi-disconnect-low-signal: radio0: wlan0 {signal_connect=-128dBm, signal_stay=-128dBm, poll_time=3s, **_strikes=3_**, drop_reason=3}
wifi-disconnect-low-signal: radio0: wlan0-1 {signal_connect=-128dBm, signal_stay=-128dBm, poll_time=3s, **_strikes=3_**, drop_reason=3}
wifi-disconnect-low-signal: found 2 enabled WiFi devices
wifi-disconnect-low-signal: wlan0: 00:27:22:76:1A:47 signal=-42dBm snr=53dBm strikes=0 (threshold: signal_connect=-128 **_strikes=0_**): good signal
wifi-disconnect-low-signal: wlan0: signal poll: 1 STAs, 0 disconnected
wifi-disconnect-low-signal: wlan0-1: no associated STAs
wifi-disconnect-low-signal: wlan0: 00:27:22:76:1A:47 signal=-41dBm snr=54dBm strikes=0 (threshold: signal_stay=-128 **_strikes=3_**): good signal
wifi-disconnect-low-signal: wlan0: signal poll: 1 STAs, 0 disconnected
wifi-disconnect-low-signal: wlan0-1: no associated STAs

So to restate, in the latter case, it first reports finding config for 3 allowed strikes (correct) then at least once acts on a 0 allowed strikes rule (incorrect) then later again reports 3 allowed strikes (correct again, but now the client is already disconnected). So something is 'up' with the strike counter.

  1. You should probably not log or even interpret non-AP wifi-iface sections
    Most of my AP have only 3 AP ( 3-VLAN) but a few have 3-STA-WDS and 3-AP-WDS. Because they act as (low traffic) 3-VLAN repeater. Yes, ugly, I know. It makes logging rather verbose with all 6 sections logging, and I worry it also takes more CPU then needed.

  2. You should probably not log or even interpret any wifi-iface sections where no connect_* options are given. My 3-SSID on 3-VLAN solutions has one isolated VLAN for Internet of Things, one for Management, one for Guests. I really only want the Guests to be disconnected or ruled.

Of course I can leave the defaults of -128dB, it works. But it makes logging rather verbose with all 6 sections logging, and I worry it also takes more CPU then needed.

Anyway. Many thanks.

how reliable is curl-websocket?

I like your simple implementation of websocket client based on libcurl, and want to use it in one of my projects. However, I was wondering how reliable it is? The project is a bot that will connect to a websocket service forever. Any advice will be highly appreciated.

wifi-disconnect-low-signal evaluate other aspects of connection

wifi-disconnect-low-signal looks robust. But on my OpenWrt, it will never trigger. There's no device having a specific SNR/dBm value, it's usually random between healthy and suffering devices. All of the time.
What differs is RX/TX, time of last query, and number of packets:

CONNECTED_MAC  -71 dBm / -93 dBm (SNR 22)  0 ms ago
        RX: 52.0 MBit/s, MCS 5, 20MHz                 459825 Pkts.
        TX: 54.0 MBit/s                               292314 Pkts.
        expected throughput: unknown

DISCONNECTED_MAC  -62 dBm / -93 dBm (SNR 31)  6800 ms ago
        RX: 1.0 MBit/s                                     5 Pkts.
        TX: 54.0 MBit/s                                    3 Pkts.
        expected throughput: unknown

As you see, noise value doesn't matter. On the unhealthy frozen device, RX is just 1mbps, no packets, and query long time ago. In even worse case, RX is 0mbps, and additionally device won't get an IP. These 2 are the only cases where i need to kick out the device in order to make it reconnect. Sadly, it's not what i can do with the magic script published.

THANK YOU!

hello,

everyone just takes without saying thank you!

so a BIG thank you from me!

doing exacly the job i wanted... FANTASTIC!

bad argument #1 to 'type' (string expected, got nil)

I'm not at all good with lua, so I don't quite get it how local wireless_status = conn:call("network.wireless", "status", {}) parses the devices, but a little dbg on line 401 shows that the radio1 returns nothing.
Any idea why iface.ifnames returns nil?

wifi-disconnect-low-signal: radio1: Device nil Section default_radio1
/usr/bin/lua: /usr/bin/wifi-disconnect-low-signal.lua:201: bad argument #1 to 'type' (string expected, got nil)
stack traceback:
[C]: in function 'type'
/usr/bin/wifi-disconnect-low-signal.lua:201: in function 'new'
/usr/bin/wifi-disconnect-low-signal.lua:404: in function 'get_wifi_devices'
/usr/bin/wifi-disconnect-low-signal.lua:438: in main chunk
[C]: ?

wifi-disconnect-low-signal does not work properly

Hello barbieri, I followed your guide but seems it doesn't work as expected. My phone still sticks to it even if the log shows it's disconnected.

Here's my config:

	option signal_connect '-60'
	option signal_stay '-70'
	option signal_strikes '2'
	option signal_poll_time '3'

Checking system log:

  1. starting the script with my phone in strong signal
Wed Aug 16 17:29:24 2023 user.debug wifi-disconnect-low-signal: radio0: phy0-ap0 {signal_connect=-60dBm, signal_stay=-70dBm, poll_time=3s, strikes=2, drop_reason=3}
Wed Aug 16 17:29:24 2023 user.debug wifi-disconnect-low-signal: radio1: disabled by config file
Wed Aug 16 17:29:24 2023 user.debug wifi-disconnect-low-signal: found 1 enabled WiFi devices
Wed Aug 16 17:29:24 2023 user.debug wifi-disconnect-low-signal: phy0-ap0: FC:BE:7B:1E:68:0D signal=-52dBm snr=46dBm strikes=0 (threshold: signal_connect=-60 strikes=0): good signal
Wed Aug 16 17:29:24 2023 user.debug wifi-disconnect-low-signal: phy0-ap0: signal poll: 1 STAs, 0 disconnected
Wed Aug 16 17:29:27 2023 user.debug wifi-disconnect-low-signal: phy0-ap0: FC:BE:7B:1E:68:0D signal=-52dBm snr=46dBm strikes=0 (threshold: signal_stay=-70 strikes=2): good signal
Wed Aug 16 17:29:27 2023 user.debug wifi-disconnect-low-signal: phy0-ap0: signal poll: 1 STAs, 0 disconnected
  1. moving away my phone
Wed Aug 16 17:32:04 2023 user.debug wifi-disconnect-low-signal: phy0-ap0: FC:BE:7B:1E:68:0D signal=-67dBm snr=31dBm strikes=0 (threshold: signal_stay=-70 strikes=2): good signal
Wed Aug 16 17:32:04 2023 user.debug wifi-disconnect-low-signal: phy0-ap0: signal poll: 1 STAs, 0 disconnected
Wed Aug 16 17:32:07 2023 user.debug wifi-disconnect-low-signal: phy0-ap0: FC:BE:7B:1E:68:0D signal=-76dBm snr=22dBm strikes=1 (threshold: signal_stay=-70 strikes=2): bad signal
Wed Aug 16 17:32:07 2023 user.debug wifi-disconnect-low-signal: phy0-ap0: signal poll: 1 STAs, 0 disconnected
Wed Aug 16 17:32:10 2023 user.debug wifi-disconnect-low-signal: phy0-ap0: FC:BE:7B:1E:68:0D signal=-76dBm snr=22dBm strikes=2 (threshold: signal_stay=-70 strikes=2): should disconnect
Wed Aug 16 17:32:10 2023 user.info wifi-disconnect-low-signal: phy0-ap0: disconnected FC:BE:7B:1E:68:0D {signal=-76dBm, noise=-98dBm, snr=22dBm, strikes=2, is_new=false}
Wed Aug 16 17:32:10 2023 user.debug wifi-disconnect-low-signal: phy0-ap0: signal poll: 1 STAs, 1 disconnected
Wed Aug 16 17:32:13 2023 user.debug wifi-disconnect-low-signal: phy0-ap0: signal poll: 0 STAs, 0 disconnected
Wed Aug 16 17:32:16 2023 user.debug wifi-disconnect-low-signal: phy0-ap0: signal poll: 0 STAs, 0 disconnected
  1. but only to find my phone still connected!

  2. then I made my phone stay in low signal area

Wed Aug 16 17:33:10 2023 user.debug wifi-disconnect-low-signal: phy0-ap0: signal poll: 0 STAs, 0 disconnected
Wed Aug 16 17:33:13 2023 user.debug wifi-disconnect-low-signal: phy0-ap0: signal poll: 0 STAs, 0 disconnected
Wed Aug 16 17:33:13 2023 user.debug wifi-disconnect-low-signal: phy0-ap0: forget FC:BE:7B:1E:68:0D
Wed Aug 16 17:33:16 2023 user.debug wifi-disconnect-low-signal: phy0-ap0: FC:BE:7B:1E:68:0D signal=-71dBm snr=28dBm strikes=1 (threshold: signal_connect=-60 strikes=0): should disconnect
Wed Aug 16 17:33:16 2023 user.info wifi-disconnect-low-signal: phy0-ap0: disconnected FC:BE:7B:1E:68:0D {signal=-71dBm, noise=-99dBm, snr=28dBm, strikes=1, is_new=true}
Wed Aug 16 17:33:16 2023 user.debug wifi-disconnect-low-signal: phy0-ap0: signal poll: 1 STAs, 1 disconnected
Wed Aug 16 17:33:19 2023 user.debug wifi-disconnect-low-signal: phy0-ap0: signal poll: 0 STAs, 0 disconnected
Wed Aug 16 17:33:22 2023 user.debug wifi-disconnect-low-signal: phy0-ap0: signal poll: 0 STAs, 0 disconnected
  1. finally I found my phone still connected to it.

Additional Info:
Router: tp-link tl-wdr6500
Version: openwrt official nightly build
Working Mode: dumb ap

Thank you in advance!

del_client tends to abruptly cut off clients more frequently if certain parameters are used

I made a few changes that improved roaming smoothness. After these changes, I have experienced almost zero case of disconnection when my phone (Android based) roam from one AP to another. Granted it still doesn't do fast roaming (a del_client limitation), but connectivity is much less likely to be severed even with more frequent roaming.

Changes in a nutshell:

  1. Changed deauth to "true"
  2. Reason hardcoded to 0 (for some reason the "reason" configuration stanza is not getting through to the del_client command somehow). Anecdotal observations show setting reason to zero (and very likely deauth = true) is actually the key to clients staying connected after moving to another AP.
  3. Added one second of sleep after the del_client command
  4. The 'is_new' variable is changed from boolean to integer, with initial value of 3
  5. Changed logic of is_new to subtract one from itself for each evaluation until it reaches zero. This makes the client stay longer at the snr_connect stage. This has the effect of making the client stick to the new AP a little longer (after a connection has been made for instance) especially if you make snr_connect a lower value than snr_stay

With these changes my main Android phone no longer experience sporadic disconnections after roaming.

Here is the code:

#!/usr/bin/lua
-- Disconnect WiFi STA (clients) based on their signal levels.
--
-- This is designed to work with openwrt's libiwinfo-lua, libuci-lua
-- and ubus services: network.wireless and hostapd.

local ubus = require("ubus")
local nixio = require("nixio")
local iwinfo = require("iwinfo")
local uci = require("uci")

local remember_gone = 60 -- remember gone STA for this amount of seconds

local openlog_args = {"wifi-disconnect-low-signal"}
local loglevel = 0
local loglevels = {"info", "debug"}
local loglevel_enabled = {}

-- cmdline arguments:
--  * --stderr: print log to stderr as well as syslog
--  * -v --verbose: increase verbosity
for i, a in ipairs(arg) do
   if i > 0 then
      if a == "--stderr" then
         openlog_args[#openlog_args + 1] = "perror"
      elseif a == "-v" or a == "--verbose" then
         loglevel = loglevel + 1
      end
   end
end

for i, level in ipairs(loglevels) do
   loglevel_enabled[level] = i <= loglevel
end

nixio.openlog(unpack(openlog_args))

function dbg(fmt, ...)
   if not loglevel_enabled["debug"] then return end
   local message = fmt:format(unpack(arg))
   nixio.syslog("debug", message)
end

function inf(fmt, ...)
   if not loglevel_enabled["info"] then return end
   local message = fmt:format(unpack(arg))
   nixio.syslog("info", message)
end

function crit(fmt, ...)
   local message = fmt:format(unpack(arg))
   nixio.syslog("crit", message)
end

function gettime()
   local sec, usec
   sec, usec = nixio.gettimeofday()
   return sec
end

local cursor = uci.cursor()
if not cursor then
   crit("Failed to open UCI cursor")
   os.exit(1)
end

local conn = ubus.connect()
if not conn then
   crit("Failed to connect to ubus")
   os.exit(1)
end

local STA = {}
STA.__index = STA

function STA.new(addr)
   local self = setmetatable({}, STA)
   self.addr = addr
   self.subject = addr:gsub(":", ""):upper()
   self.signal = 0
   self.noise = 0
   self.strikes = strikes or 0
   self.is_new = 3
   self.disconnected_at = nil
   self.gone_at = nil
   return self
end

function STA:__tostring()
   local now = gettime()
   local disconnected, gone
   if self.disconnected_at == nil then
      disconnected = ""
   else
      disconnected = string.format(
         ", disconnected=%ds", now - self.disconnected_at)
   end
   if self.gone_at == nil then
      gone = ""
   else
      gone = string.format(
         ", gone=%ds", now - self.gone_at)
   end
   return string.format(
      "%s {" ..
         "signal=%ddBm, " ..
         "noise=%ddBm, " ..
         "snr=%ddBm, " ..
         "strikes=%d, "..
         "is_new=%s"..
         "%s%s}",
      self.addr,
      self.signal,
      self.noise,
      self.snr,
      self.strikes,
      tostring(self.is_new),
      disconnected,
      gone)
end

function STA:update(info)
   self.signal = info.signal
   if self.signal > 0 then
      self.signal = -128 - (127 - self.signal)
   end
   self.noise = info.noise
   self.snr = self.signal - self.noise
end

function STA:matches(matcher)
   local len = matcher.max_len
   while len >= matcher.min_len do
      local subject = self.subject:sub(1, len)
      if matcher[subject] then
         return true
      end
      len = len - 1
   end
   return false
end

-- creates a table with [prefix] = true and sets the prefix length
-- range as max_len and min_len. Then the matcher should use
-- string.sub(1, len) for len in closed range min_len to max_len,
-- checking if the prefix exists in the matcher.
function prefix_list_matcher(str)
   if str == nil or str == "" then
      return nil
   end

   local matcher = {}
   local max_len = 0
   local min_len = 12
   for p in str:gmatch("([^,]+)") do
      if p ~= "" then
         matcher[p] = true

         local plen = p:len()
         if max_len < plen then
            max_len = plen
         end
         if min_len > plen then
            min_len = plen
         end
      end
   end
   if max_len < 1 then
      return nil
   end

   matcher.max_len = max_len
   matcher.min_len = min_len

   return matcher
end

-- defines an uci config option given its name, how to convert it to
-- native type and the default value
function DeviceOpt(name, type, default)
   return { name = name, type = type, default = default }
end

local Device = {}
Device.__index = Device
Device.conf_options = {
   signal_connect = DeviceOpt("signal_connect", tonumber, -128),
   signal_stay = DeviceOpt("signal_stay", tonumber, -128),
   snr_connect = DeviceOpt("signal_snr_connect", tonumber, 0),
   snr_stay = DeviceOpt("signal_snr_stay", tonumber, 0),
   poll_time = DeviceOpt("signal_poll_time", tonumber, 3),
   strikes = DeviceOpt("signal_strikes", tonumber, 3),
   drop_reason = DeviceOpt("signal_drop_reason", tonumber, 0),
   whitelist = DeviceOpt("signal_whitelist", prefix_list_matcher, nil),
   blacklist = DeviceOpt("signal_blacklist", prefix_list_matcher, nil),
}

function Device.new(ifname, conf_section)
   local self = setmetatable({}, Device)
   self.ifname = ifname
   local api = iwinfo.type(self.ifname)
   self.iw = iwinfo[api]

   for key, opt in pairs(Device.conf_options) do
      local conf = cursor:get("wireless", conf_section, opt.name)
      self[key] = opt.type(conf) or opt.default
   end

   self.stas = {} -- addr -> STA
   self.updated_at = nil
   return self
end

function Device:__tostring()
   local connect, stay

   if self.snr_connect > 0 then
      connect = string.format("snr_connect=%ddBm", self.snr_connect)
   else
      connect = string.format("signal_connect=%ddBm", self.signal_connect)
   end
   if self.snr_stay > 0 then
      stay = string.format("snr_stay=%ddBm", self.snr_stay)
   else
      stay = string.format("signal_stay=%ddBm", self.signal_stay)
   end

   return string.format(
      "%s {" ..
         "%s, " ..
         "%s, " ..
         "poll_time=%ds, " ..
         "strikes=%d, " ..
         "drop_reason=%d}",
      self.ifname,
      connect,
      stay,
      self.poll_time,
      self.strikes,
      self.drop_reason)
end

function Device:get_sta(addr)
   local sta = self.stas[addr]

   if sta == nil then
      sta = STA.new(addr)

      if self.whitelist ~= nil and not sta:matches(self.whitelist) then
         dbg("%s: ignored %s (whitelist)", self.ifname, addr)
         return nil
      end

      if self.blacklist ~= nil and sta:matches(self.blacklist) then
         dbg("%s: ignored %s (blacklist)", self.ifname, addr)
         return nil
      end

      self.stas[addr] = sta
   elseif sta.is_new > 0 then
      sta.is_new = sta.is_new - 1
   end

   return sta
end

function Device:next_poll()
   return self.updated_at + self.poll_time
end

function Device:update_stas(now)
   if self.updated_at ~= nil and now - self.updated_at < self.poll_time then
      return nil
   end

   local stas = {
      connected = {},
      disconnected = {},
   }
   self.updated_at = now

   local assoclist = self.iw.assoclist(self.ifname)
   if not assoclist or next(assoclist) == nil then
      dbg("%s: no associated STAs", self.ifname)
      self:cleanup_stas(stas.connected)
      return stas
   end

   for addr, info in pairs(assoclist) do
      local sta = self:get_sta(addr)
      if sta ~= nil and sta.disconnected_at == nil then
         sta:update(info)

         if self:should_disconnect_sta(sta) then
            self:disconnect_sta(sta)
            sta.disconnected_at = now
            sta.gone_at = now
            stas.disconnected[#stas.disconnected + 1] = sta
            stas.disconnected[addr] = sta
         else
            sta.gone_at = nil
            stas.connected[#stas.connected + 1] = sta
            stas.connected[addr] = sta
         end
      end
   end

   dbg("%s: signal poll: %i STAs, %i disconnected",
       self.ifname, #stas.connected + #stas.disconnected,
       #stas.disconnected)

   self:cleanup_stas(stas.connected)
   return stas
end

function Device:cleanup_stas(connected)
   local to_remove = {}
   local now = self.updated_at
   for addr, sta in pairs(self.stas) do
      if connected[addr] == nil then
         if sta.gone_at == nil then
            dbg("%s: %s is gone", self.ifname, addr)
            sta.gone_at = now
         elseif now - sta.gone_at > remember_gone then
            to_remove[#to_remove + 1] = addr
         end
      end
   end
   for _, addr in ipairs(to_remove) do
      dbg("%s: forget %s", self.ifname, addr)
      self.stas[addr] = nil
   end
end

function Device:should_disconnect_sta(sta)
   local label, ref_strikes, value
   if sta.is_new > 0 then
      if self.snr_connect > 0 then
         label = "snr_connect"
      else
         label = "signal_connect"
      end
      ref_strikes = 0
   else
      if self.snr_stay > 0 then
         label = "snr_stay"
      else
         label = "signal_stay"
      end
      ref_strikes = self.strikes
   end

   local ref = self[label]
   local value = sta[label:gsub("_%a+$", "")]

   function msg(status)
      dbg("%s: %s signal=%ddBm snr=%ddBm strikes=%d " ..
             "(threshold: %s=%d strikes=%d): %s",
          self.ifname, sta.addr, sta.signal, sta.snr, sta.strikes,
          label, ref, ref_strikes, status)
   end

   if ref <= value then
      msg("good signal")
      sta.strikes = 0
      return false
   end

   sta.strikes = sta.strikes + 1
   if ref_strikes > sta.strikes then
      msg("bad signal")
      return false
   end

   msg("should disconnect")
   return true
end

function Device:disconnect_sta(sta)
   local endpoint = "hostapd." .. self.ifname
   conn:call(endpoint, "del_client", {
                addr = sta.addr,
                reason = 0,
                deauth = "true",
                ban_time = 0,
   })
   nixio.nanosleep(1)
   inf("%s: disconnected %s", self.ifname, tostring(sta))
end

-- returns an array of all enabled devices as instances of Device.
function get_wifi_devices()
   local wireless_status = conn:call("network.wireless", "status", {})
   local devices = {}
   for name, radio in pairs(wireless_status) do
      if radio.disabled then
         dbg("%s: disabled by config file", name)
      else
         for _, iface in ipairs(radio.interfaces) do
            if iface.config.mode == "ap" then
               local dev = Device.new(iface.ifname, iface.section)
               if dev ~= nil then
                  devices[#devices + 1] = dev
                  dbg("%s: %s", name, tostring(dev))
               end
            end
         end
      end
   end
   return devices
end

function update_devices_and_sleep(devices)
   local now = gettime()
   local next_poll_time = now + 60
   for _, dev in ipairs(devices) do
      dev:update_stas(now)
      local dev_next_poll_time = dev:next_poll()
      if next_poll_time > dev_next_poll_time then
         next_poll_time = dev_next_poll_time
      end
   end

   local seconds = next_poll_time - now
   if seconds > 0 then
      nixio.nanosleep(seconds)
   end
end

nixio.signal(3, "dfl")
nixio.signal(15, "dfl")

local devices = {}
while #devices == 0 do
   devices = get_wifi_devices()
   dbg("found %d enabled WiFi devices", #devices)
end

while true do
   local _, err = pcall(function () update_devices_and_sleep(devices) end)
   if err ~= nil then
      dbg("quit: %s", tostring(err))
      break
   end
end

nixio.closelog()
conn:close()

make a suggestion

The tool is very easy to use, can the author add luci to facilitate compilation into openwrt, thank you.
I think the author's is better than luci-app-dawn.

Adapter config

Seeing that on the description you this:
Edit the /etc/config/wireless either manually or using uci and add the option signal_NAME 'value' to config wifi-device sections.

Looking at the example, you have it configured under config wifi-iface 'default_radio0' - can you clarify which one is the right approach?

Adding another question, I see these events:
wifi-disconnect-low-signal: wlan0: E0:2B:E9:D7:EF:7E signal=-78dBm snr=21dBm strikes=1 (threshold: signal_connect=-65 strikes=0): should disconnect
wifi-disconnect-low-signal: wlan0: disconnected E0:2B:E9:D7:EF:7E {signal=-78dBm, noise=-99dBm, snr=21dBm, strikes=1, is_new=true}

My expectation is that the device should disconnect immediately, right? Not seeing the same happening on Windows device.

Thanks in advance.

[SOLVED] Disconnecting is not working anymore

Hi,

i found out that method used to disconnect STA i not valid anymore (don't know when was it changed).

Method that is used in script is wnm_disassoc_imminent and has to be changed to del_client

To make script work again, I had to modify this function:

function Device:disconnect_sta(sta)
local endpoint = "hostapd." .. self.ifname
conn:call(endpoint, "wnm_disassoc_imminent", {
addr = sta.addr,
duration = 120,
abridged = true,
})
inf("%s: disconnected %s", self.ifname, tostring(sta))
end

TO THIS:

function Device:disconnect_sta(sta)
local endpoint = "hostapd." .. self.ifname
conn:call(endpoint, "del_client", {
addr = sta.addr,
reason = 1,
deauth = true,
ban_time = 120000,
})
inf("%s: disconnected %s", self.ifname, tostring(sta))
end

efl-win64-install.py not work

Archlinux is no have this toolchain. MinGW moved in the AUR:

$ python3 ./efl-win64-install.py 
missing toolchain (x86_64-w64-mingw32-gcc) in $PATH

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.