#!/usr/bin/env lua --[[ Copyright 2017 Marcos Gutierrez Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-3.0 ]]-- require "ubus" local nixio = require "nixio",require "nixio.fs" local json = require 'luci.jsonc' local utils = require("lime.utils") local function printJson (obj) print(json.stringify(obj)) end local conn = ubus.connect() if not conn then error("Failed to connect to ubus") end local function spectral_scan(msg) if utils.is_installed("fft-eval") == false then local result = { error = "fft-eval not installed" } printJson(result) return end local device = utils.shell_quote(msg.device) local spectrum = msg.spectrum local result = { spectrum = {} } local fd = assert(io.open("/sys/class/net/" .. device .. "/phy80211/name")) local phy = assert(fd:read("*l")) fd:close() local path_ath9k = "/sys/kernel/debug/ieee80211/" .. phy .. "/ath9k/" local freqs = { } freqs["2ghz"] = { 2412, 2422, 2432, 2442, 2452, 2462 } freqs["5ghz"] = { } -- scan all possible channels if spectrum == "2ghz" or spectrum == "5ghz" then samples = sample_whole_spectrum(device, path_ath9k, freqs[spectrum]) elseif spectrum == "current" then samples = sample_current_channel(path_ath9k) end samples = json.parse( samples ) -- Convert values to string (avoid ubus bug) for _, dev in pairs(samples[1].data) do samples[1].data[_][1] = tostring(samples[1].data[_][1]) samples[1].data[_][2] = tostring(samples[1].data[_][2]) end local json_reply = { samples = samples, epoch = os.time() } result.spectrum = json_reply printJson(result) end function sample_current_channel(path_ath9k) -- sample current channel only, no freq hopping -- grab only one sample per trigger nixio.fs.writefile(path_ath9k .. "spectral_count", "1") -- empty buffer nixio.fs.readfile(path_ath9k .. "spectral_scan0") -- trigger sampling nixio.fs.writefile(path_ath9k .. "spectral_scan_ctl", "manual") nixio.fs.writefile(path_ath9k .. "spectral_scan_ctl", "trigger") print("fft_eval " .. path_ath9k .. "spectral_scan0") local samples = utils.unsafe_shell(utils.shell_quote("fft_eval " .. path_ath9k .. "spectral_scan0")) nixio.fs.writefile(path_ath9k .. "spectral_scan_ctl", "disable") return samples end function sample_whole_spectrum(device, path_ath9k, freqs) -- grab samples over the whole spectrum -- grab only one sample per trigger nixio.fs.writefile(path_ath9k .. "spectral_count", "1") -- empty buffer nixio.fs.readfile(path_ath9k .. "spectral_scan0") -- trigger sampling hopping channels nixio.fs.writefile(path_ath9k .. "spectral_scan_ctl", "chanscan") local cmd = "iw dev " .. device .. " scan" if #freqs > 0 then cmd = cmd .. " freq " .. table.concat(freqs, " ") end utils.unsafe_shell(cmd) nixio.fs.writefile(path_ath9k .. "spectral_scan_ctl", "disable") local samples = utils.unsafe_shell("fft_eval " .. path_ath9k .. "spectral_scan0") return samples end local methods = { spectral_scan = { device = 'value', spectrum = 'value' } } if arg[1] == 'list' then printJson(methods) end if arg[1] == 'call' then local msg = io.read() msg = json.parse(msg) if arg[2] == 'spectral_scan' then spectral_scan(msg) else printJson({ error = "Method not found" }) end end