跳转至

Wlan

一、概述

wifi 操作:主要介绍模组支持的 wifi 相关功能(对于仅支持 wifiscan 的模块, 仅 init/scan/scanResult 函数是可用的。例如: Air780EXXX 等仅支持 wifiscan)。

AP 应用:AP 是 Access Point 的缩写,即无线接入点,它是一个无线网络的中心节点,可以看成是一个服务器。它作为一个网络的中心节点,提供无线接入服务,其他的无线设备允许接入该节点,所有接入该节点设备的无线信号数据都要通过它才能进行交换和互相访问。一般的无线路由器、网关、热点就是工作在 AP 模式下,AP 节点和 AP 节点之间允许相互连接;

AP 应用可参考以太网连接外部网络,生成 WiFi 热点为 WiFi 终端设备提供接入,支持以太网 lan 模式为其他以太网设备提供接入

STA 应用:STA 是 Station 的缩写,它是无线网络中的一个终端站点设备,可以看成是一个客户端,一般来说,处在 STA 模式下的设备本身不接受无线的接入,该设备连接到 AP 节点进行网络访问,STA 模式下的设备之间的通信可以通过 AP 进行转发实现;

扫描 应用:WiFiSCAN 是指通过无线设备(如智能手机、路由器、物联网设备等)主动扫描周围可用的 WiFi 网络,以获取其基本信息(如 SSID、信号强度、加密方式、频段等)的过程。它是无线通信领域中一项基础且重要的功能,广泛应用于网络配置、设备连接、信号优化及安全检测等场景;

二、演示功能概述

本示例将演示如何使用 Air8101 工业引擎的 AP 应用,STA 应用和扫描应用。

三、准备硬件环境

参考:硬件环境清单,准备以及组装好基本硬件环境。

2.1 Air8101 核心板

3.2 PC 电脑

WIN10 以及以上版本的 WINDOWS 系统;

3.3 数据通信线

USB 数据线(其一端为 Type-C 接口,用于连接 Air8101)。

Air8101 核心板购买链接:Air8101 核心板 WiFi 4G 以太网 蓝牙 720P显示屏 200万拍照-淘宝网

四、准备软件环境

4.1 下载调试工具

使用说明参考:Luatools 下载和详细使用

五、软硬件资料

5.1 源码及固件

参考:Air8101 软件环境清单,准备好软件环境。

  1. 烧录工具:参考 Luatools 工具使用说明
  2. 本demo开发测试时使用的固件为Air8101 V2010 版本固件,本demo对固件版本没有什么特殊要求,所以你如果要测试本demo时,可以直接使用最新版本的内核固件;如果发现最新版本的内核固件测试有问题,可以使用我们开发本demo时使用的内核固件版本来对比测试;
  3. Air8101 开发板脚本文件参考:https://gitee.com/openLuat/LuatOS/tree/master/module/Air8101/demo/wlan
  4. LuatOS 运行所需要的 lib 文件:使用 Luatools 烧录时,勾选 添加默认 lib 选项,使用默认 lib 脚本文件。准备好软件环境之后,接下来查看 Air8101 核心板使用说明将本篇文章中演示使用的项目文件烧录到 Air8101 开发板中。

5.2 demo 使用 api 介绍

本教程使用 api 接口为:

https://docs.openluat.com/osapi/core/wlan/

https://docs.openluat.com/osapi/core/netdrv/

https://docs.openluat.com/osapi/ext/dhcpsrv/

https://docs.openluat.com/osapi/core/httpsrv/

六、代码示例介绍

6.1 作为 STA 连接 wifi

--[[
@module  wifi_sta
@summary wifi_sta模块 
@version 1.0
@date    2025.10.20
@author  魏健强
@usage 本文为wifi_sta功能模块,核心逻辑为
1、模块连接wifi;
2、发送http请求,测试网络;
本文件没有对外接口,直接在其他功能模块中require "wifi_sta"就可以加载运行;
]] 
-- wifi的STA相关事件
sys.subscribe("WLAN_STA_INC", function(evt, data)
    -- evt 可能的值有: "CONNECTED", "DISCONNECTED"
    -- 当evt=CONNECTED, data是连接的AP的ssid, 字符串类型
    -- 当evt=DISCONNECTED, data断开的原因, 整数类型
    log.info("收到STA事件", evt, data)
end)

function test_sta()
    wlan.init()
    log.info("执行STA连接操作")
    wlan.connect("test", "HZ88888888")
    -- 等待wifi_sta网络连接成功
    while not socket.adapter(socket.LWIP_STA) do
        -- 在此处阻塞等待wifi连接成功的消息"IP_READY"
        -- 或者等待1秒超时退出阻塞等待状态;
        -- 注意:此处的1000毫秒超时不要修改的更长;
        sys.waitUntil("IP_READY", 1000)
    end
    while true do
        local code, headers, body = http.request("GET", "https://httpbin.air32.cn/bytes/2048", nil, nil, {adapter=socket.LWIP_STA,timeout=5000,debug=false}).wait()
        log.info("http执行结果", code, headers, body and #body)
        sys.wait(2000)
    end
end

function ip_ready_handle(ip, adapter)
    log.info("ip_ready_handle",ip, adapter)
    if adapter == socket.LWIP_STA then
        log.info("wifi sta 链接成功")
    end
end

sys.taskInit(test_sta)
sys.subscribe("IP_READY", ip_ready_handle)

6.2 开启一次 wifi 扫描,并注册获取 wifi 扫描结果的回调函数

--[[
@module  wifi_scan
@summary wifi_scan模块 
@version 1.0
@date    2025.10.20
@author  魏健强
@usage 本文为wifi扫描功能模块,核心逻辑为
1、开启WiFi扫描;
2、打印扫描结果;

本文件没有对外接口,直接在其他功能模块中require "wifi_scan"就可以加载运行;
]] 
local scan_result = {}

wlan.init()
function test_scan()
    while true do
        log.info("10秒后执行wifi扫描")
        sys.wait(10 * 1000)
        wlan.scan()
    end
end

function scan_done_handle()
    local result = wlan.scanResult()
    for k,v in pairs(result) do
        log.info("scan", (v["ssid"] and #v["ssid"] > 0) and v["ssid"] or "[隐藏SSID]", v["rssi"], (v["bssid"]:toHex()))
        if v["ssid"] and #v["ssid"] > 0 then
            table.insert(scan_result, v["ssid"])
        end
    end
    log.info("scan", "aplist", json.encode(scan_result))
end

sys.subscribe("WLAN_SCAN_DONE", scan_done_handle)

sys.taskInit(test_scan)

6.3 ap 配网

--[[
@module  ap_config_net
@summary wifi配网功能模块 
@version 1.0
@date    2025.10.20
@author  魏健强
@usage 本文为wifi配网功能模块,核心逻辑为
1、开启wifi_ap热点;
2、模块开启http服务器;
3、用户通过手机等设备连接wifi_ap热点,访问http网页进行wifi配网;
直接使用Air8101核心板硬件测试即可;

本文件没有对外接口,直接在其他功能模块中require "ap_config_net"就可以加载运行;
]]
dhcpsrv = require("dhcpsrv")

-- 初始化LED灯, 根据实际GPIO修改
-- local LEDA= gpio.setup(12, 0, gpio.PULLUP)

local scan_result = {}

local function create_ap()
    log.info("执行AP创建操作", "test2")
    wlan.createAP("test2", "HZ88888888")
    netdrv.ipv4(socket.LWIP_AP, "192.168.4.1", "255.255.255.0", "192.168.4.1")
    dhcpsrv.create({
        adapter = socket.LWIP_AP
    })
end

local function handle_http_request(fd, method, uri, headers, body)
    -- log.info("httpsrv", method, uri, json.encode(headers), body)
    log.info("httpsrv", "fd", fd, "method", method, "uri", uri, "headers", json.encode(headers), "body", body)
    -- /led是控制灯的API
    if uri == "/led/1" then
        -- LEDA(1)
        log.info("led", "on")
        return 200, {}, "ok"
    elseif uri == "/led/0" then
        -- LEDA(0)
        log.info("led", "off")
        return 200, {}, "ok"
        -- 处理消息
    elseif uri == "/msg" then
        local messageData = json.decode(body) -- 假设消息是 JSON 格式
        if messageData and messageData.message then
            log.info("Received message:", messageData.message)
            -- 处理接收到的消息,例如保存、转发、响应等等
            return 200, {}, "Message received: " .. messageData.message
        end

        -- 扫描AP
    elseif uri == "/scan/go" then
        wlan.scan()
        log.info("scan", "start")
        return 200, {}, "ok"
        -- 前端获取AP列表
    elseif uri == "/scan/list" then
        return 200, {
            ["Content-Type"] = "applaction/json"
        }, (json.encode({
            data = scan_result,
            ok = true
        }))
        -- 前端填好了ssid和密码, 那就连接吧
    elseif uri == "/connect" then
        if method == "POST" and body and #body > 2 then
            local jdata = json.decode(body)
            if jdata and jdata.ssid then
                -- 开启一个定时器联网, 否则这个情况可能会联网完成后才执行完
                sys.timerStart(wlan.connect, 500, jdata.ssid, jdata.passwd)
                return 200, {}, "ok"
            end
        end
        return 400, {}, "ok"
        -- 根据ip地址来判断是否已经连接成功
    elseif uri == "/connok" then
        return 200, {
            ["Content-Type"] = "applaction/json"
        }, json.encode({
            ip = socket.localIP()
        })
    elseif uri == "/send" then
        if method == "POST" and body and #body > 2 then
            local jdata = json.decode(body)
            if jdata and jdata.msg then
                log.info("Received message:", jdata.msg)
                return 200, {}, "Message received"
            end
        end
        return 400, {}, "Bad Request"

    end
    -- 其他情况就是找不到了
    return 404, {}, "Not Found" .. uri
end

local function wifi_networking()
    httpsrv.start(80, handle_http_request, socket.LWIP_AP)
    log.info("web", "pls open url http://192.168.4.1/")
end

-- wifi扫描成功后, 会有WLAN_SCAN_DONE消息, 读取即可
local function scan_done_handle()
    local result = wlan.scanResult()
    scan_result = {}
    for k, v in pairs(result) do
        log.info("scan", (v["ssid"] and #v["ssid"] > 0) and v["ssid"] or "[隐藏SSID]", v["rssi"], (v["bssid"]:toHex()))
        if v["ssid"] and #v["ssid"] > 0 then
            table.insert(scan_result, v["ssid"])
        end
    end
    log.info("scan", "aplist", json.encode(scan_result))
end

local function main_task()
    wlan.init()
    create_ap()
    wifi_networking()
end

local function ip_ready_handle()
    -- wifi联网成功后, 在这里进行后续应用逻辑的扩展处理
    log.info("wlan", "已联网")
    -- sys.taskInit(sockettest)
end

sys.subscribe("WLAN_SCAN_DONE", scan_done_handle)
sys.subscribe("IP_READY", ip_ready_handle)
sys.taskInit(main_task)

七、结果验证

7.1 STA 结果示例

7.2 wifi 扫描结果示例

7.3 AP 配网结果示例

八、总结

至此,使用 wlan 核心库演示的 STA、wifi 扫描和 wifi 配网功能已经结束。如果大家在实际操作中遇到技术难题,欢迎联系合宙技术人员。