下面将从 原理、详细实现步骤、关键点、优缺点 以及 一个具体的开发示例 几个方面来阐述其实现方案。

AirKiss 核心原理
AirKiss 的核心思想是 “信道窃听” 和 “数据编码”,它巧妙地利用了 Wi-Fi 通信中无处不在的 Beacon 帧,将 Wi-Fi 的 SSID(网络名称)和密码信息“藏”在看似普通的信道噪音中,让手机通过监听这些“噪音”来解密出连接信息。
整个过程可以分解为两个阶段:
-
第一阶段:发现与信道协商
- 设备端(如智能插座):进入 AirKiss 模式,主动广播一个特殊的、包含固定标识符(如
TIC)的 AirKiss 数据包,这个数据包本身不包含任何 Wi-Fi 信息。 - 手机端(App):监听并搜索这个特殊的 AirKiss 数据包,一旦找到,手机就知道附近有一个设备正在等待配网。
- 信道协商:手机会随机选择一个 Wi-Fi 信道(1-13),并在此信道上持续发送一个包含
TIC标识符的数据包,设备端则不断切换信道,监听这个来自手机的TIC包,一旦设备端在某个信道上收到了手机发来的TIC包,双方就建立了一个临时的、私有的通信信道。
- 设备端(如智能插座):进入 AirKiss 模式,主动广播一个特殊的、包含固定标识符(如
-
第二阶段:数据传输
(图片来源网络,侵删)- 信道确定后,双方都知道了在哪个信道上进行“秘密”通信。
- 手机端:将目标 Wi-Fi 的 SSID 和 Password 进行编码,编码方式通常是将 SSID 和密码拼接成一个字符串,然后进行 CRC32 校验,生成一个校验码,这个
(SSID + Password + CRC32)的数据流被调制到 Wi-Fi 的物理层,以非常高的速率(约 2-4Mbps) 在协商好的信道上持续发送,这种高速发送的信号在频谱上看起来就像是白噪声,不会对正常的 Wi-Fi 通信造成明显干扰。 - 设备端:在协商好的信道上高速接收这些“噪声”数据,接收到足够的数据后,它会进行解码,分离出 SSID、Password 和 CRC32 校验码,设备端会验证 CRC32 是否正确,如果正确,就证明数据传输无误,手机和设备成功“握手”。
-
第三阶段:连接 Wi-Fi
- 设备端:从解码出的数据中获取到 SSID 和 Password,然后使用这些信息去尝试连接指定的 Wi-Fi 网络。
- 手机端:在发送完数据后,会等待设备端的连接反馈,设备成功连接后,会通过一个约定的方式(如 UDP 广播)发送一个成功信号,手机收到后,就知道配网成功,并通知用户。
一个形象的比喻:
想象在一个嘈杂的房间里(多个 Wi-Fi 信道),设备端小声问:“有人吗?”(广播 TIC 包)。
手机听到后,走到一个角落里(选择一个信道),大声喊:“我在这里!”(在特定信道广播 TIC 包)。
设备端找到角落后,手机开始用一种只有他们俩能听懂的快速暗语(高速发送编码数据)来传递 Wi-Fi 密码。
设备端听懂暗语后,就拿着密码去开门(连接 Wi-Fi),然后回头告诉手机门已经打开了(发送成功信号)。
详细实现步骤(从开发者角度)
假设我们要开发一个支持 AirKiss 的智能设备(如 ESP32)。
硬件准备
- 一款支持 Wi-Fi 的 MCU,如 ESP32、ESP8266 等,ESP32 因其双核和强大的 Wi-Fi 功能,是首选。
软件环境
- Arduino IDE 或 PlatformIO。
- 安装相关的库,如
AirKiss库(有多个开源实现,如esp32-airkiss)。
实现流程
A. 设备端固件开发

-
初始化 Wi-Fi 模式:
- 将 Wi-Fi 设置为 Station 模式(客户端模式),因为我们最终是要连接路由器的。
- 设置一个回调函数,用于处理 AirKiss 接收到的数据。
-
进入 AirKiss 监听模式:
- 调用 AirKiss 库的初始化函数,开始监听来自手机的
TIC包。 - 库的内部逻辑会自动进行信道切换和信道协商。
- 调用 AirKiss 库的初始化函数,开始监听来自手机的
-
处理接收到的数据:
- 一旦 AirKiss 库成功解码出 SSID 和 Password,它会通过回调函数通知你。
- 在回调函数中,获取到 SSID 和 Password。
-
执行连接:
- 使用获取到的 SSID 和 Password,调用
WiFi.begin(ssid, password)尝试连接 Wi-Fi。 - 在
WiFi.onEvent()中监听SYSTEM_EVENT_STA_CONNECTED和SYSTEM_EVENT_STA_GOT_IP事件,以判断连接状态。
- 使用获取到的 SSID 和 Password,调用
-
通知手机:
- 方法一(推荐): 设备成功连接 Wi-Fi 并获取 IP 后,通过 UDP 向一个固定的 IP 地址(如
255.255.255广播地址)和端口发送一个简单的成功消息(如{"result":"success"}),手机 App 在发送完数据后会监听这个端口,收到即代表成功。 - 如果手机和设备在同一个临时网络中,设备可以通过 HTTP 请求或 TCP 连接直接通知手机。
- 方法一(推荐): 设备成功连接 Wi-Fi 并获取 IP 后,通过 UDP 向一个固定的 IP 地址(如
B. 手机 App 开发
-
触发配网:
- 用户在 App 中点击“添加设备”或“配网”按钮。
- App 开始扫描附近的 AirKiss 设备。
-
发送
TIC包进行信道协商:- 扫描到设备后,App 随机选择一个信道(如 6),并在此信道上以固定间隔(如 100ms)发送
TIC包,持续几秒钟。 - App 初始化 AirKiss 编码模块。
- 扫描到设备后,App 随机选择一个信道(如 6),并在此信道上以固定间隔(如 100ms)发送
-
编码并发送 Wi-Fi 信息:
- 从 App 配置中获取当前连接的 Wi-Fi 的 SSID 和 Password。
- 将 SSID 和 Password 拼接,并计算 CRC32 校验码。
- 将组合数据
(SSID + Password + CRC32)转换成数据流。 - 关键:在同一个协商好的信道上,以高速率(2.4Mbps)发送这个数据流,持续发送 5-10 秒,确保设备端有足够的时间接收。
-
等待设备反馈:
- 发送完毕后,App 切换到监听模式,在约定的 UDP 端口上等待来自设备的成功消息。
- 如果在一定时间内(如 10 秒)收到消息,则提示用户“配网成功”。
- 如果超时未收到,则提示“配网失败”,可以重试。
关键技术与注意事项
- 高速率发送:
这是 AirKiss 技术的精髓,通过将速率提高到 2-4Mbps,可以在短时间内发送足够多的数据,同时其信号频谱被展宽,功率谱密度降低,看起来更像背景噪声,避免了与标准 Wi-Fi 信号(1-54Mbps)的冲突。
- CRC32 校验:
用于保证数据在传输过程中的完整性,如果设备端解码后的 CRC32 与手机端计算的不一致,说明数据出错,应丢弃并等待重传。
- 信道协商:
这是解决“鸡生蛋还是蛋生鸡”问题的关键,没有协商,设备不知道该听哪个信道,手机也不知道该往哪个信道喊。
- 抗干扰能力:
高速率发送本身就具备一定的抗干扰性,实现上通常会采用多次重发和前向纠错等技术来提高可靠性。
- 安全性:
- AirKiss 本身并不加密 Wi-Fi 密码,它是在开放的物理层进行广播的,它不适合在安全性要求极高的环境中使用(如企业网络),它的安全依赖于“距离”,攻击者必须在设备附近才能截获数据,对于家庭消费级产品,这种便捷性通常可以接受其安全风险。
- 兼容性:
- 不同的 AirKiss 开源库或厂商的实现可能存在细微差别(如
TIC标识符、波特率、UDP 端口等),开发时需确保设备端和手机端使用的是兼容的协议版本。
- 不同的 AirKiss 开源库或厂商的实现可能存在细微差别(如
优缺点分析
优点
- 极致便捷:用户无需手动输入复杂的密码,只需在 App 中点击一下即可,体验非常好。
- 无需额外硬件:完全基于标准的 Wi-Fi 协议,不需要蓝牙、NFC 等额外模块,成本低。
- 速度快:整个过程通常在 5-15 秒内完成,非常高效。
- 跨平台:技术原理通用,手机 App 可以轻松地在 iOS 和 Android 上实现。
缺点
- 安全性较低:密码明文传输,易受中间人攻击(在物理距离内)。
- 易受干扰:在 Wi-Fi 信号非常复杂或干扰严重的环境中,协商和数据传输阶段可能会失败。
- 无法支持复杂网络:无法处理需要证书、企业认证、隐藏 SSID 或 5GHz Wi-Fi 的网络。
- 距离限制:由于是物理层广播,有效距离受 Wi-Fi 信号强度限制,通常在 10 米以内。
简单代码示例(基于 ESP32 和 Arduino)
设备端代码 (ESP32)
#include <WiFi.h>
#include <WiFiUdp.h>
#include "AirKiss.h"
// AirKiss 对象
AirKiss airkiss;
// Wi-Fi 连接成功后的回调
void WiFiEvent(WiFiEvent_t event) {
switch (event) {
case SYSTEM_EVENT_STA_CONNECTED:
Serial.println("Connected to AP");
break;
case SYSTEM_EVENT_STA_GOT_IP:
Serial.print("Got IP address: ");
Serial.println(WiFi.localIP());
// 连接成功,通知手机
notifyPhone();
break;
case SYSTEM_EVENT_STA_DISCONNECTED:
Serial.println("Disconnected from AP");
WiFi.reconnect();
break;
default:
break;
}
}
// 通知手机函数
void notifyPhone() {
WiFiUDP udp;
const int udpPort = 8266; // 约定的端口
udp.begin(udpPort);
const char *message = "{\"result\":\"success\"}";
udp.beginPacket("255.255.255.255", udpPort); // 广播地址
udp.write(message);
udp.endPacket();
udp.stop();
Serial.println("Notified phone of success.");
}
void setup() {
Serial.begin(115200);
// 注册 Wi-Fi 事件回调
WiFi.onEvent(WiFiEvent);
// 启动 AirKiss
Serial.println("Starting AirKiss...");
airkiss.start(); // 库会自动处理监听和解析
}
void loop() {
// AirKiss 库需要在 loop 中被调用,以处理内部状态机
airkiss.loop();
// AirKiss 解析成功,它会内部调用回调
// 这里我们不需要做太多事,等待 WiFiEvent 即可
delay(10);
}
手机端代码逻辑 (伪代码)
// Android/iOS App 伪代码
public void startAirKissConfig() {
// 1. 获取当前 Wi-Fi 的 SSID 和 Password
String ssid = getCurrentWifiSSID();
String password = getCurrentWifiPassword();
// 2. 初始化 AirKiss 编码器
AirKissEncoder encoder = new AirKissEncoder();
String dataToTransmit = encoder.encode(ssid, password); // 内部会拼接并计算 CRC
// 3. 开始信道协商和数据发送
// a. 扫描设备,找到一个设备
// b. 随机选择一个信道,channel 6
// c. 在 channel 6 上发送 TIC 包,等待设备响应
// d. 协商成功后,在 channel 6 上以 2.4Mbps 速率发送 dataToTransmit 数据流,持续 8 秒
// 4. 发送完毕,开始监听反馈
startListeningForFeedback();
}
private void startListeningForFeedback() {
// 在约定的 UDP 端口 (如 8266) 上监听
// 收到 {"result":"success"} 消息后,弹出 "配网成功" 提示
// 10 秒后未收到,则提示 "配网失败,请重试"
}
AirKiss 是一个巧妙、高效且实用的智能设备配网方案,它通过利用 Wi-Fi 物理层的特性,在保证用户体验和成本效益之间取得了很好的平衡,对于绝大多数消费级智能硬件产品来说,它是一个成熟且值得优先考虑的配网技术,开发者只需选择一个成熟的库,并按照上述步骤进行集成,即可快速实现 AirKiss 功能。
