Skip to content

Instantly share code, notes, and snippets.

@thomo
Last active November 28, 2021 11:07
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
  • Save thomo/1d8d87eedca8a518a1d8cdd0f12ec9fb to your computer and use it in GitHub Desktop.
Save thomo/1d8d87eedca8a518a1d8cdd0f12ec9fb to your computer and use it in GitHub Desktop.
Wifi Scanner with ESP8266 + TFT ST7735B (NodeMCU)
-- Tested with
-- NodeMCU 3.0.0.0 built on nodemcu-build.com provided by frightanic.com
-- branch: release
-- commit: d4ae3c364bd8ae3ded8b77d35745b7f07879f5f9
-- release:
-- release DTS: 202105102018
-- SSL: false
-- build type: float
-- LFS: 0x0 bytes total capacity
-- modules: bit,file,gpio,net,node,spi,tmr,uart,ucg,wifi
-- build 2021-11-22 17:49 powered by
-- Lua 5.1.4 on SDK 3.0.1-dev(fce080e)
-- setup SPI and connect display
function init_spi_display()
-- Hardware SPI CLK = GPIO14
-- Hardware SPI MOSI = GPIO13
-- Hardware SPI MISO = GPIO12 (not used)
-- Hardware SPI /CS = GPIO15 (not used)
-- CS, D/C, and RES can be assigned freely to available GPIOs
local cs = 8 -- GPIO15, pull-down 10k to GND
local dc = 4 -- GPIO2
local res = 0 -- GPIO16
local bus = 1
spi.setup(bus, spi.MASTER, spi.CPOL_LOW, spi.CPHA_LOW, 8, 8)
-- we won't be using the HSPI /CS line, so disable it again
gpio.mode(8, gpio.INPUT, gpio.PULLUP)
disp = ucg.st7735_18x128x160_hw_spi(bus, cs, dc, res)
end
function calculateSignalLevel(rssi, numLevels)
local MIN_RSSI = -100
local MAX_RSSI = -55
if rssi <= MIN_RSSI then
return 0
elseif rssi >= MAX_RSSI then
return numLevels - 1
else
local inputRange = (MAX_RSSI - MIN_RSSI)
local outputRange = (numLevels - 1)
return (rssi - MIN_RSSI) * outputRange / inputRange
end
end
function extractWifiData(k, line)
local wd = {}
wd["ssid"] = k
wd["authmode"], rssi, wd["bssid"], wd["channel"] = string.match(line, "([^,]+),([^,]+),([^,]+),([^,]+)")
wd["rssi"] = tonumber(rssi)
wd["level"] = calculateSignalLevel(wd["rssi"], 4)
wd["age"] = 1
return wd
end
function updateWifiData(oldData, line)
local wd = extractWifiData("",line)
oldData["age"] = oldData["age"] - 1
oldData["rssi"] = wd["rssi"]
oldData["level"] = wd["level"]
oldData["channel"] = wd["channel"]
return oldData
end
function filter(t, filterIter)
local out = {}
for k, v in pairs(t) do
if filterIter(k, v) then out[k] = v end
end
return out
end
function updateWifiTable(t)
for k,v in pairs(wifidata) do
v["age"] = v["age"] + 1
end
for k,v in pairs(t) do
if wifidata[k] then
wifidata[k] = updateWifiData(wifidata[k], v)
else
wifidata[k] = extractWifiData(k, v)
end
end
wifidata = filter(wifidata, function(k, v) return v["age"] < 10 end)
end
function drawIndicator(fillIndicator, fillBlue, x, y, w, h)
if fillIndicator then
if fillBlue then
disp:setColor(79, 122, 240) -- a blue color
else
disp:setColor(31, 240, 87) -- a green color
end
disp:drawBox(x, y-h, w, h)
else
disp:setColor(0, 0, 0)
disp:drawBox(x+1, y-h+1, w-2, h-2)
disp:setColor(80, 80, 80)
disp:drawFrame(x, y-h, w, h)
end
end
function printWifiLine(y, h, data)
if data["ssid"] == nil then
disp:setClipRange(0, y-h, 160, h)
disp:setColor(0, 0, 0)
disp:drawBox(0, y-h, 160, h)
disp:undoClipRange()
else
disp:setClipRange(0, y-h, 138, h)
disp:setColor(0, 0, 0)
disp:drawBox(0, y-h, 138, h)
disp:setClipRange(0, y-h, 125, h)
disp:setPrintPos(0,y)
disp:setColor(255, 255, 255)
disp:print(data["ssid"])
disp:undoClipRange()
local w = disp:getStrWidth(data["channel"])
disp:setClipRange(138-w-4, y-h, w+4, h)
disp:setPrintPos(138-w,y)
disp:print(data["channel"])
disp:undoClipRange()
drawIndicator(data["level"] >= 0, data["authmode"] == 0, 140, y, 4, 3)
drawIndicator(data["level"] >= 1, data["authmode"] == 0, 145, y, 4, 5)
drawIndicator(data["level"] >= 2, data["authmode"] == 0, 150, y, 4, 7)
drawIndicator(data["level"] >= 3, data["authmode"] == 0, 155, y, 4, 9)
end
end
function updateDispData(dispdata, data)
local changed = false
for i,key in ipairs({"ssid", "level", "authmode", "channel"}) do
if dispdata[key] ~= data[key] then
changed = true
dispdata[key] = data[key]
end
end
return changed
end
function loop()
wifi.sta.getap(updateWifiTable)
local lineHeight = 12
local curRow = lineHeight
local alines = {}
for k,v in pairs(wifidata) do
table.insert(alines, v)
end
if table.getn(alines) > 1 then
table.sort(alines, function(a,b) return a["rssi"] > b["rssi"] or (a["rssi"] == b["rssi"] and a["ssid"] < b["ssid"]) end)
end
for i=1,9 do table.insert(alines, {ssid=nil}) end
for i,v in ipairs(alines) do
if i > 9 then
break
end
curRow = curRow + lineHeight
if updateDispData(dispdata[i], v) then
printWifiLine(curRow, lineHeight, dispdata[i])
end
end
end
wifidata = {}
dispdata = {}
for i=1,9 do dispdata[i] = {} end
init_spi_display()
disp:begin(ucg.FONT_MODE_TRANSPARENT)
disp:setFont(ucg.font_helvB08_hr)
disp:setRotate270()
disp:setColor(255, 255, 255)
disp:setPrintDir(0)
disp:clearScreen()
disp:setColor(255, 255, 255)
local str = "== WIFI SCANNER =="
disp:setPrintPos((160 - disp:getStrWidth(str))/2,12)
disp:print(str)
wifi.setmode(wifi.STATION)
loop()
tmr.create():alarm(5000, tmr.ALARM_AUTO, function() loop() end)
@thomo
Copy link
Author

thomo commented Nov 22, 2021

Rev 2 is compatible with NodeMCU 3.0.0.0 powered by Lua 5.1.4 on SDK 3.0.1-dev(fce080e), required modules are: bit,file,gpio,net,node,spi,tmr,uart,ucg,wifi

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment