四博智联产品售后

 找回密码
 立即注册
搜索
查看: 6736|回复: 1

802.11格式

[复制链接]

237

主题

286

帖子

1675

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
1675
发表于 2015-6-10 16:46:32 | 显示全部楼层 |阅读模式
frame协议格式

09lec4.pdf

1.06 MB, 下载次数: 2714

回复

使用道具 举报

237

主题

286

帖子

1675

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
1675
 楼主| 发表于 2015-6-12 17:07:51 | 显示全部楼层
smart connection 或 smart link的实现

乐鑫的esp8266 是一颗非常有意思的物联网soc芯片。但目前它不提供smartconnection,或者叫smart link的功能.实际上smart connection的实现只不过是利用了wifi的数据帧长度来实现的,下面就定义一下简单的利用长度来复用数据的方案。并在esp8266上实现smartconnection。

如何在长度中复用数据
1. wifi的数据包都经过加密,所以能利用的信息无非就是数据包的长度信息
2.我们使用0-16 共17种不同的长度来表示数据,(这相当于17进制)
  其中 0用于表示 起始位, 1-16用于表示  数据 ,这样精度为4位
3.定义的简单协议如下
   
    0
    0
    位置低4位
    位置低4位补码
    位置高4位
    位置高4位补码
    数据低4位
    数据低4位补码
    数据高4位
    数据高4位补码
   也就是一共用10个不同长度的帧来表示一个字节,通过启动位,位置,位置补码,值 ,值补码。来组合一个字节。 之所以有位置,是因为wifi帧容易丢包,通过加入位置信息,就可以在多次发送中尽量补齐这些信息。


下面直接写出代码,发送端使用c# ,接收端使用 esp8266 的sdk.以下只是个demo虽然可用,但没有经过严格的测试。:)



以下是发送端c#代码实现:
        byte calcrc_1byte(byte abyte)   
        {   
           byte i,crc_1byte;     
           crc_1byte=0;                //设定crc_1byte初值为0  
            for(i = 0; i < 8; i++)   
            {   
              if(((crc_1byte^abyte)&0x01) > 0)   
              {   
                   crc_1byte^=0x18;     
                   crc_1byte>>=1;   
                   crc_1byte|=0x80;   
              }         
              else     
              {
                  crc_1byte>>=1;   
              }
               abyte>>=1;         
             }   
             return crc_1byte;   
        }   
        byte calcrc_bytes(byte[] p,int len)  
        {  
            byte crc=0;
            int i = 0;
            for (i = 0; i < len;i++ )
              //len为总共要校验的字节数  
             {
                 crc = calcrc_1byte((byte)(crc^p));
             }  
         return crc;  //若最终返回的crc为0,则数据传输正确  
        }
        byte[] MakeCRC8(byte[] src)
        {
            byte crc = calcrc_bytes(src,src.Length);
            byte[] rtlval = new byte[src.Length + 1];
            for (int i = 0; i < src.Length; i++)
                rtlval = src;
            rtlval[src.Length] = crc;
            return rtlval;
        }

        private byte[] SmartLinkEncode(byte[] src)
        {
            byte[] rtlval = null;
            int curidx = 0;
            rtlval = new byte[src.Length * 10];
            byte tmp;
            for (int i = 0; i < src.Length; i++)
            {
                rtlval[curidx++] = 0;
                rtlval[curidx++] = 0;
                tmp = (byte)(i & 0xF);
                rtlval[curidx++] = (byte)(tmp+1);//pos_L
                rtlval[curidx++] = (byte)((15-tmp)+1);//~pos_L
                tmp = (byte)((i & 0xF0)>>4);
                rtlval[curidx++] = (byte)(tmp + 1);//pos_H
                rtlval[curidx++] = (byte)((15 - tmp) + 1);//~pos_H
                tmp = (byte)(src & 0xF);
                rtlval[curidx++] = (byte)(tmp + 1);//val_L
                rtlval[curidx++] = (byte)((15 - tmp) + 1);//~val_L
                tmp = (byte)((src & 0xF0)>>4);
                rtlval[curidx++] = (byte)(tmp + 1);//val_H
                rtlval[curidx++] = (byte)((15 - tmp) + 1);//~val_H
            }
            return rtlval;
        }

        byte[] MakeIotMooncake_SSID_PWD(String ssid, String pwd)
        {
            byte[] SSID = Encoding.ASCII.GetBytes(ssid);
            byte[] PWD = Encoding.ASCII.GetBytes(pwd);
            byte[] rtlval = new byte[SSID.Length + PWD.Length + 1];
            int curidx = 0;
            for (int i = 0; i < SSID.Length; i++)
                rtlval[curidx++] = SSID;
            rtlval[curidx++] = 0x0a;//'\n'  split by '\n'
            for (int i = 0; i < PWD.Length; i++)
                rtlval[curidx++] = PWD;
            return rtlval;
        }
      
        private void buttonStart_Click(object sender, EventArgs e)
        {
            buttonStart.Enabled = false;
            buttonUdpDisc.Enabled = false;
            UdpClient s = new UdpClient();
            
            //IPEndPoint iep = new IPEndPoint(IPAddress.Parse("192.168.2.1"), 8910);
            IPEndPoint iep = new IPEndPoint(IPAddress.Parse("192.168.2.100"), 8910);
            byte[] dummybuf = new byte[18];

            byte[] sendbuf = MakeIotMooncake_SSID_PWD(this.textBoxSSID.Text, this.textBoxPWD.Text);

            sendbuf = MakeCRC8(sendbuf);
            byte[] encBuf = SmartLinkEncode(sendbuf);
            int delayms = 5;
            DateTime beginTime = DateTime.Now;
            while (true)
            {
                delayms++;
                if (delayms > 7)
                    delayms = 5;
                for (int i = 0; i < encBuf.Length; i++)
                {
                    s.Send(dummybuf, encBuf, iep);
                    Thread.Sleep(delayms);
                }
                Thread.Sleep(200);
                if ((DateTime.Now - beginTime).TotalSeconds >= 12)
                    break;
           }
            buttonStart.Enabled = true;

        }




以下是8266中的实现

#include "ets_sys.h"
#include "osapi.h"
#include "mem.h"

#include "user_interface.h"

#include "version.h"

typedef enum _encrytion_mode {
    ENCRY_NONE           = 1,
    ENCRY_WEP,
    ENCRY_TKIP,
    ENCRY_CCMP
} ENCYTPTION_MODE;

struct router_info {
    SLIST_ENTRY(router_info)     next;

    u8 bssid[6];
    u8 channel;
    u8 authmode;

    u16 rx_seq;
    u8 encrytion_mode;
    u8 iv[8];
    u8 iv_check;
};

//smartlink var def begin
enum enumSL_Checking_stage
{
SL_CH_STAGE_INIT = 0x1,
SL_CH_STAGE_SENDER_LOCKING = 0x2,
SL_CH_STAGE_SENDER_LOCKED = 0x4
};
#define RECEVEBUF_MAXLEN (90)
#define SCAN_TIMEINTERVAL (1500)
u8 SL_sendMacLock=0;
u8 SL_sendMac[6];
int SL_sendChannel=-1;
uint32 SL_sendMacLockTime=0;
u8 SL_protocol_OnByte[10];
u8 SL_protocol_OnByteCurIdx=0;
u8 SL_protocol_ReceveBuf[RECEVEBUF_MAXLEN];//todo use os_malloc();
u8 SL_protocol_ReceveBuf_Len=0;
u8 SL_Checking_stage = SL_CH_STAGE_INIT;
//smartlink var def end
//smartlink fun def begin
unsigned char calcrc_1byte(unsigned char abyte)   
   {   
      unsigned char i,crc_1byte;     
      crc_1byte=0;                //设定crc_1byte初值为0  
      for(i = 0; i < 8; i++)   
       {   
         if(((crc_1byte^abyte)&0x01))   
            {   
              crc_1byte^=0x18;     
              crc_1byte>>=1;   
              crc_1byte|=0x80;   
             }         
          else     
             crc_1byte>>=1;   
          abyte>>=1;         
        }   
        return crc_1byte;   
   }   
   unsigned char calcrc_bytes(unsigned char *p,unsigned char len)  
   {  
    unsigned char crc=0;  
    while(len--) //len为总共要校验的字节数  
{  
   crc=calcrc_1byte(crc^*p++);  
}  
return crc;  //若最终返回的crc为0,则数据传输正确  
   }
   
int SmartLinkDecode(u8* pOneByte)
{
int i = 0;
u8 pos=0,val=0;
u8 n0,n1;
if( !(0==pOneByte[0]&&0==pOneByte[1]) ) return -9;
n0 = (pOneByte[2]-1);
n1 = (pOneByte[3]-1);
if( (n1+n0) != 15 )
{
//os_printf("n0=%d,n1=%d\n",n0,n1);
return -1;
}
pos = (n0&0xf);
n0 = (pOneByte[4]-1);
n1 = (pOneByte[5]-1);
if( (n1+n0) != 15 ) return -2;
pos |= (n0&0xf)<<4;
n0 = (pOneByte[6]-1);
n1 = (pOneByte[7]-1);
if( (n1+n0) != 15 ) return -3;
val = (n0&0xf);
n0 = (pOneByte[8]-1);
n1 = (pOneByte[9]-1);
if( (n1+n0) != 15 ) return -4;
val |= (n0&0xf)<<4;
if( (int)pos >= (int)RECEVEBUF_MAXLEN )
return -5;
if( SL_protocol_ReceveBuf[pos] == val && SL_protocol_ReceveBuf_Len>2 )
{//begin crc8
if(  calcrc_bytes(SL_protocol_ReceveBuf,SL_protocol_ReceveBuf_Len) == SL_protocol_ReceveBuf[SL_protocol_ReceveBuf_Len] )
{
SL_protocol_ReceveBuf[SL_protocol_ReceveBuf_Len+1]='\0';
os_printf("\ngot ssid-pwd show it\n");
os_printf("%s\n",SL_protocol_ReceveBuf);
return 0;
}
}
else
{
SL_protocol_ReceveBuf[pos] = val;
os_printf("[%d]=%d\n",pos,val);
if( pos > SL_protocol_ReceveBuf_Len )
{
SL_protocol_ReceveBuf_Len = pos;
//os_printf("new LEN=%d\n",SL_protocol_ReceveBuf_Len);
}
return SL_CH_STAGE_SENDER_LOCKED;
}
return 99;
}

//buf point to MAC
void SL_Checker(u8* buf,int len,int channel)
{
int funret;
if( len > 16 )
return;
if( (system_get_time() - SL_sendMacLockTime) > 70000)
{
SL_Checking_stage =SL_CH_STAGE_INIT;
//os_printf("into SL_CH_STAGE_INIT\n");
}
if(SL_CH_STAGE_INIT == SL_Checking_stage && len == 0)
{
if(SL_sendMacLock == 0)
{os_memcpy(SL_sendMac,buf,6);}
SL_sendChannel=channel;
SL_sendMacLockTime=system_get_time();
SL_Checking_stage = SL_CH_STAGE_SENDER_LOCKING;
SL_protocol_OnByteCurIdx = 0;
SL_protocol_OnByte[SL_protocol_OnByteCurIdx++]=len;
//os_printf("into SL_CH_STAGE_SENDER_LOCKING\n");
}
else if( SL_CH_STAGE_SENDER_LOCKING == SL_Checking_stage )
{
if( os_memcmp(SL_sendMac,buf,6) == 0 )
{
if( len == 0)
{
SL_protocol_OnByte[SL_protocol_OnByteCurIdx++]=len;
SL_Checking_stage = SL_CH_STAGE_SENDER_LOCKED;
//os_printf("into SL_CH_STAGE_SENDER_LOCKED\n");
}
else
{
SL_Checking_stage =SL_CH_STAGE_INIT;
SL_protocol_OnByteCurIdx=0;
}
SL_sendMacLockTime=system_get_time();
}
}
else if( SL_CH_STAGE_SENDER_LOCKED == SL_Checking_stage )
{
if( os_memcmp(SL_sendMac,buf,6) == 0 )
{
if( len == 0 )
{
if(SL_sendMacLock == 0)
{os_memcpy(SL_sendMac,buf,6);}
SL_sendChannel=channel;
SL_Checking_stage = SL_CH_STAGE_SENDER_LOCKING;
SL_protocol_OnByteCurIdx = 0;
SL_protocol_OnByte[SL_protocol_OnByteCurIdx++]=len;
os_printf("resync  into SL_CH_STAGE_SENDER_LOCKING\n");
}
else
{
SL_protocol_OnByte[SL_protocol_OnByteCurIdx++]=len;
}
SL_sendMacLockTime=system_get_time();
}
}
if(SL_protocol_OnByteCurIdx>=10)
{
funret = SmartLinkDecode(SL_protocol_OnByte);
os_printf("Decode ret=%d\n",funret);
if( SL_CH_STAGE_SENDER_LOCKED == funret )
{
SL_Checking_stage = SL_CH_STAGE_SENDER_LOCKED ;
SL_sendMacLock = 1;
}
SL_Checking_stage =SL_CH_STAGE_INIT;
SL_protocol_OnByteCurIdx=0;
}
}

//smartlink fun def end



SLIST_HEAD(router_info_head, router_info) router_list;

os_timer_t channel_timer;
uint8 current_channel;
uint16 channel_bits;

typedef struct framectrl_80211
{
//buf[0]
u8 Subtype:4;
u8 Type:2;
u8 Protocol:2;
//buf[1]
u8 ToDS:1;
u8 FromDS:1;
u8 MoreFlag:1;
u8 Retry:1;
u8 PwrMgmt:1;
u8 MoreData:1;
u8 Protectedframe:1;
u8 Order:1;
}framectrl_80211,*lpframectrl_80211;
void wifi_scan_done(void *arg, STATUS status);

void ICACHE_FLASH_ATTR
wifi_promiscuous_rx(uint8 *buf, uint16 len)
{
uint16 i;
lpframectrl_80211 framectrl;
struct router_info *info = NULL;
framectrl = (lpframectrl_80211)buf;
//os_printf("RA:" MACSTR ",", MAC2STR(buf + 4), len);
//os_printf("SA:" MACSTR ",", MAC2STR(buf + 4+6), len);
//os_printf("DA:" MACSTR ",len %d\n", MAC2STR(buf + 4+6+6), len);
SLIST_FOREACH(info, &router_list, next) {
if ((buf[1] & 0x01) == 0x01) { // just toDS
if (os_memcmp(info->bssid, buf + 4, 6) == 0) {
if (current_channel - 1 != info->channel) { // check channel
return;
} else {
break;
}
}
}
}

if (info == NULL) {
return;
}

if ((buf[0] == 0x08 || buf[0] == 0x88) && (buf[1] & 0x01) == 0x01) {
//only data frame and ToDS==1 只分析数据帧,会容易处理一些
if (info->rx_seq != (*(uint16 *)(buf + 22)) >> 4) {
info->rx_seq = (*(uint16 *)(buf + 22)) >> 4;

if (info->encrytion_mode != 0) {
if ((buf[0] & 0x80) == 0) {
len -= 24;
} else {
len -= 26;
}
if (info->encrytion_mode == ENCRY_NONE) {
len -= 40;
} else if (info->encrytion_mode == ENCRY_WEP){
len = len - 40 - 4 - 4;
} else if (info->encrytion_mode == ENCRY_TKIP) {
len = len - 40 - 12 - 8;
} else if (info->encrytion_mode == ENCRY_CCMP) {
len = len - 40 - 8 - 8;
}

if (len == 3 || len == 23 || (len >= 593 && len <= 848) || len == 1099 || len == 1199 || (len > 28 && len <= 60)) {
if (len >= 593 && len <= 848) {
len -= 593;
// os_printf(MACSTR ",len --- d x\n", MAC2STR(buf + 4), len + 593, len);
} else {
// os_printf(MACSTR ",len %d\n", MAC2STR(buf + 4), len);
}
} else {
// os_printf(MACSTR ",len --- %d\n", MAC2STR(buf + 4), len);
}
//os_printf("%d\n", len);
//Smartlink checker
SL_Checker(buf+4,len,info->channel);//对长度进行协议测试
} else {
if (info->authmode == AUTH_OPEN) {
info->encrytion_mode = ENCRY_NONE;
os_printf(MACSTR ", channel %d, mode %d\n", MAC2STR(info->bssid), info->channel, info->encrytion_mode);
} else if (info->authmode == AUTH_WEP) {
info->encrytion_mode = ENCRY_WEP;
os_printf(MACSTR ", channel %d, mode %d\n", MAC2STR(info->bssid), info->channel, info->encrytion_mode);
} else {
if (info->iv_check == 0) {
if (buf[0] == 0x08) {
os_memcpy(info->iv, buf + 24, 8);
} else if (buf[0] == 0x88) {
os_memcpy(info->iv, buf + 26, 8);
}
info->iv_check = 1;
} else {
uint8 *local_iv;
if (buf[0] == 0x08) {
local_iv = buf + 24;
} else if (buf[0] == 0x88) {
local_iv = buf + 26;
}
if (info->iv[2] == local_iv[2] && local_iv[2] == 0) {
info->encrytion_mode = ENCRY_CCMP;
os_printf(MACSTR ", channel %d, mode %d\n", MAC2STR(info->bssid), info->channel, info->encrytion_mode);
} else {
info->encrytion_mode = ENCRY_TKIP;
os_printf(MACSTR ", channel %d, mode %d\n", MAC2STR(info->bssid), info->channel, info->encrytion_mode);
}
}
}
}
}
}
}

void ICACHE_FLASH_ATTR
channel_timer_cb(void *arg)
{
uint8 i;
if( SL_sendChannel>0 && SL_sendMacLock == 1)
{
wifi_set_channel(SL_sendChannel);
os_printf("locked Smartlink channel=%d\n",SL_sendChannel);
return;
}
for (i = current_channel; i < 14; i++) {
if ((channel_bits & (1 << i)) != 0) {
current_channel = i + 1;
wifi_set_channel(i);
os_printf("current channel2 %d--------------------------------------------%d\n", i, system_get_time());
os_timer_arm(&channel_timer, SCAN_TIMEINTERVAL, 0);
break;
}
}

if (i == 14) {
current_channel = 1;
for (i = current_channel; i < 14; i++) {
if ((channel_bits & (1 << i)) != 0) {
current_channel = i + 1;
wifi_set_channel(i);
os_printf("current channel3 %d--------------------------------------------%d\n", i, system_get_time());
os_timer_arm(&channel_timer, SCAN_TIMEINTERVAL, 0);
break;
}
}
}
}

void ICACHE_FLASH_ATTR
wifi_scan_done(void *arg, STATUS status)
{
uint8 ssid[33];

channel_bits = 0;
current_channel = 1;

struct router_info *info = NULL;

while((info = SLIST_FIRST(&router_list)) != NULL){
SLIST_REMOVE_HEAD(&router_list, next);

os_free(info);
}

if (status == OK) {
uint8 i;
struct bss_info *bss = (struct bss_info *)arg;

while (bss != NULL) {
os_memset(ssid, 0, 33);

if (os_strlen(bss->ssid) <= 32) {
os_memcpy(ssid, bss->ssid, os_strlen(bss->ssid));
} else {
os_memcpy(ssid, bss->ssid, 32);
}

if (bss->channel != 0) {
struct router_info *info = NULL;

os_printf("ssid %s, channel %d, authmode %d, rssi %d\n",
ssid, bss->channel, bss->authmode, bss->rssi);
channel_bits |= 1 << (bss->channel);

info = (struct router_info *)os_zalloc(sizeof(struct router_info));
info->authmode = bss->authmode;
info->channel = bss->channel;
os_memcpy(info->bssid, bss->bssid, 6);

SLIST_INSERT_HEAD(&router_list, info, next);
}
bss = STAILQ_NEXT(bss, next);
}

for (i = current_channel; i < 14; i++) {
if ((channel_bits & (1 << i)) != 0) {
current_channel = i + 1;
wifi_set_channel(i);
os_printf("current channel1 %d--------------------------------------------%d\n", i, system_get_time());
break;
}
}

wifi_promiscuous_enable(1);
wifi_set_promiscuous_rx_cb(wifi_promiscuous_rx);

os_timer_disarm(&channel_timer);
os_timer_setfn(&channel_timer, channel_timer_cb, NULL);
os_timer_arm(&channel_timer, SCAN_TIMEINTERVAL, 0);
} else {
os_printf("err, scan status %d\n", status);
}
}

void ICACHE_FLASH_ATTR
system_init_done(void)
{
SLIST_INIT(&router_list);

wifi_station_scan(NULL,wifi_scan_done);
}


void user_init(void)
{
os_printf("smart connection OR smart link demo v 1001\n"

wifi_set_opmode(STATION_MODE);

system_init_done_cb(system_init_done);
}

http://blog.sina.com.cn/s/blog_69f669470102vf1m.html
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|手机版|小黑屋|四博智联 Inc. ( 粤ICP备15034758号-1

GMT+8, 2020-8-15 01:06 , Processed in 0.148288 second(s), 25 queries .

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表