【iOS】一键配网 广播实现

一、环境

目的:将设备入网
1.UDP框架 GCDAsyncUdpSocket;
2.加密方式,采用aes_cfb128 iv为0 ;
3.抓包验证wireshark

二、结果

1.利用发送包的长度发送数据, 每次发送11bit数据,设备端根据规则可以收到数据,最后连接到路由器;

三、流程图

APP 路由器 设备 手机连接到路由器 发送UDP广播包 当前信道发送 扫描信道 ,根据长度解析,接收数据,组包 解析到ssid和pwd 连接到路由器 APP 路由器 设备

四、流程

1.初始化UDPSocket
_castSocket = [[GCDAsyncUdpSocket alloc] initWithDelegate:self delegateQueue:_castQueue];

(1)开启广播 Broadcast;

if (![_castSocket enableBroadcast:YES error:&error]) {
     UdpLog(@"enableBroadcast error:%@",error);
}

(2)接收数据 beginReceiving;

if (![_castSocket beginReceiving:&error]) {
     UdpLog(@"beginReceiving error:%@",error);
}

(3)指定端口 不指定则会随机分配;

2、数据发送

(1)发送地址
端口与设备端协商,这里以60000举例
local:port -> 192.168.2.255 : 60000 + index
(2)数据

说明
dataByte总长度(1) + flag(1) + ssidLen(1) + pwdLen(1) + ssid + pwd + checkSum(2)
ssid:ssid为中文则采用utf-8编码,其他则为ASCII编码
pwdpwd需要加密
checkSum校验和
//判断中文
- (BOOL)isChinese:(NSString *) str{
    for(int i=0; i< [str length];i++){
        int a = [str characterAtIndex:i];
        if( a > 0x4E00 && a < 0x9FFF){
            return YES;
        }
    }
    return NO;
}
//aes加密
- (NSData *)aesEncryptData:(uint8_t *)crypt_data len:(int)crypt_len keyData:(NSData *)keydata{
    unsigned char *keyResult=(Byte*)[keydata bytes];
    AES_KEY aes_key;
    unsigned char *outByte = NULL;
    outByte = (unsigned char *)malloc(crypt_len+1);
    memset(outByte, 0, crypt_len+1);
    AES_set_encrypt_key(keyResult, 128, &aes_key);
    int number = 0;
    NSData *ivData = [NSData dataWithBytes:&number length:1];
    unsigned char *ivResult = (Byte*)[ivData bytes];
    NSData *numData = [NSData dataWithBytes:&number length:1];
    int *numResult = (int *)[numData bytes];
    AES_cfb128_encrypt(crypt_data,outByte,crypt_len, &aes_key,ivResult,numResult ,AES_ENCRYPT);
    NSData *Decrydata = [NSData dataWithBytes:outByte length:crypt_len];
    return Decrydata;
}

(3)发送结构
利用广播的数据长度length发送数据 每次发送11bit数据,
帧头与设备端协商,这里以0x480举例
数据分为

说明
帧头0x480 , 0x481,0x482,0x483…
帧数据index(4bit) + data(7bit)

bit7 帧头固定为1 ,数据帧固定为0;
发送数按组发送 一组是一个帧头*2 + 8个数据帧;

[self.castClient sendData:[self zeroDataWithCount:value] toHost:_broadcastIP port:60000+_sendCount];

(4)转码
由于bit7是帧头位, 所以每次只能发送6bit数据,就需要对整个数据 进行8bit->6bit转码
例如

 0x 11 22 (0b 0001 0001 0010 0010 (高位到低位)) -> 1000 1000 0100 0100(低位到高位)
-> 100010 000100 010000(低位到高位) -> 010001 001000  0000010(高位到低位) ->0x11 08 02 
    int  bitCount = 6;
    int  dataLength = (int)data.length;
    Byte codeData[dataLength * bitCount];
    int  outLength = (dataLength * 8 + bitCount - 1) /bitCount;
    Byte outData[outLength];
    Byte *dataByte = (Byte *)data.bytes;
    for (int i = 0; i < dataLength; i ++) {
        for (int j = 0; j < 8; j++) {
            codeData[i * 8 + j] = (dataByte[i] >> j) & 0x01;
        }
    }
    for (int i = 0; i < outLength; i++) {
        outData[i] = 0;
        for (int j = 0; j < bitCount; j ++) {
            outData[i] |= codeData[i * bitCount + j] << j;
        }
    }
    NSData *tempCodeData = [NSData dataWithBytes:outData length:sizeof(outData)];
    return  tempCodeData;

(5)传输规则
每包之间间隔20ms;间隔时间可按实际情况调整
(1) 帧头*2 (0x480 -> 1152)
(2) 帧数据 8 (组序号<<7 + data[index])
(3) 帧头
2 (0x481 -> 1153)
(4) 帧数据 8
(5) 帧头
2 (0x482 -> 1154)

(6) 帧数据 *8

(6)通过抓包可以看到发送的数据
在这里插入图片描述
五、总结
通过抓信道包也可以看到,但是要切换信道,切信道比较麻烦,也可以通过共享网络热点的方式切换;

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值