openwrt中自动选择最优无线信道

在物联网产品运营的过程中,产品所处的环境非常复杂,各种无线信号相互干扰,

人为的干预切换设备的信道效果甚微,并且面对大量设备时也力不从心,可以综合环境因素让设备开机或定时自动选择当前最优信道。

/**
create by iversondeng168
*/
#include <sys/time.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <errno.h>
#include <syslog.h>
#include <string.h>
#include <ctype.h>
#include <time.h>
#include <fcntl.h>
#include <memory.h>
#include <signal.h>


#define  UI8      unsigned char
#define  I8       char
#define  UI32     unsigned int 
#define  I32      int

//本地网卡mac地址
#define READ_MACADDR                               "cat /sys/devices/platform/ar934x_wmac/ieee80211/phy0/macaddress"

//使用iwinfo命令搜索附近WiFi信息
#define SCAN_WIFI                                  "iwinfo wlan0 scan"



//国内wifi 5.8G可用频点
static const int chan_arrays_support[] = 
{
    36,40,44,48,

    149,153,157,161,165
};


#define CHANNEL_SUPPORT_SIZE                      (sizeof(chan_arrays_support) / sizeof(int))


//使用管道派生子进程执行命令
I8* cmd_system(const I8* command)
{    
     I8* result = "";    
     FILE *fpRead;    
	 fpRead = popen(command, "r");    
	 I8 buf[1024];    
	 memset(buf,'\0',sizeof(buf));    
	 while(fgets(buf,1024-1,fpRead)!=NULL)
	 {        
	    result = buf; 
	 }
	 
	 if(fpRead!=NULL)        
	 	pclose(fpRead);  
	 
	 return result;
}




//十六进制字符转十进制
I32 hex_char_to_int(I8 in)
{
    if(in >= '0' && in <= '9')
        return in - '0';

    if(in >= 'a' && in <= 'f')
        return (in - 'a') + 10;

    if(in >= 'A' && in <= 'F')
        return (in - 'A') + 10;

    return 0;
}



//在字串符中找出子字符串并返回起始位置
I32 find_substring(const char *pSrc, const char *pDst)  
{  
    int i, j;  
    for (i=0; pSrc[i]!='\0'; i++)  
    {  
        if(pSrc[i]!=pDst[0])  
            continue;         
        j = 0;  
        while(pDst[j]!='\0' && pSrc[i+j]!='\0')  
        {  
            j++;  
            if(pDst[j]!=pSrc[i+j])  
            break;  
        }  
        if(pDst[j]=='\0')  
            return i;  
    }  
    return -1;  
}  



//使用uci命令指定设置具体信道
static void chan_switch(int is_effect,int chan)
{
	UI8 randval;
	I8*retpt;
    UI8 i;
    UI8 is_support;
    I8 cmds[128];

	memset(cmds,0,128);
    
    
    if(chan)
	{
	 
	   is_support = 0;

       for(i=0;i < CHANNEL_SUPPORT_SIZE;i++)
	   {
          if(chan_arrays_support[i] == chan){
			  is_support = 1;
			  break;
		  }
	   }

	   if(!is_support) chan = 0;
	}
    
    randval = (!chan) ? chan_arrays_support[rand() % CHANNEL_SUPPORT_SIZE] : chan;

#if 0
    ///执行选择channel
	printf("sel chan is %d\n",randval);
#endif

    retpt = cmd_system("uci get wireless.radio0.channel");
	if(atoi(retpt) == randval){
		#if 0
		printf("sel chan is equal to the sys cur channel\n");
		#endif
		return;
	}

    sprintf(cmds,"uci set wireless.radio0.channel=%d",randval);

    cmd_system(cmds);

	cmd_system("uci set wireless.@wifi-iface[0].hidden=1");

    cmd_system("uci commit wireless");

	if(is_effect){
		sleep(1);
		cmd_system("wifi down && wifi");
	}
}



//使用uci命令提交设置但需要WiFi重启生效
void chan_commit(void)
{
   I8*retpt;
   I8*tmpt;
   UI8 i;
   UI32 randval;

   UI8 macaddr[6];
   I8 cmds[128];


   memset(cmds,0,128);
  
   retpt = cmd_system(READ_MACADDR);
   
   tmpt = strtok(retpt,":");

   i = 0;
   while(tmpt){
	   macaddr[i++] =  hex_char_to_int(tmpt[0]) * 16 + hex_char_to_int(tmpt[1]);//atoi(tmpt);
	   tmpt         =  strtok(NULL,":");
   }

   //让mac来决定channel
   randval = macaddr[0] + macaddr[1] + macaddr[2] + macaddr[3] + macaddr[4] + macaddr[5];
   #if 0
   printf("mac randval=%d\t",randval);
   #endif

   randval %= CHANNEL_SUPPORT_SIZE;

   #if 0
   printf("sel channel is %d\n",chan_arrays_support[randval]);
   #endif

   sprintf(cmds,"uci set wireless.radio0.channel=%d",chan_arrays_support[randval]);

   cmd_system(cmds);

   cmd_system("uci set wireless.@wifi-iface[0].hidden=1");

   cmd_system("uci commit wireless");
}




/**
自动搜索当前环境可用WiFi信道,
信道占用最少,并且信号强度最弱,
则选择该信道设为自身信道.
*/
UI8 chan_auto(void)
{
	 #define CHAN_CNT_SIZE           CHANNEL_SUPPORT_SIZE
	 #define MAX_BUF_CACHE           (1024)

     //对应信道统计
	 I32 chans_cnt[CHAN_CNT_SIZE]   = {0};
	 I32 tmp_chan;
	 UI8 chans_few                  = 0;
	 UI8 tmp[CHAN_CNT_SIZE];

	 I32 i,j,k;
  
     I8 buf[MAX_BUF_CACHE]; 
	 I32 retval; 

     //对应信道强度最大值统计 
	 I32 chans_signal[CHAN_CNT_SIZE];
     I32 tmp_sig;
	 UI8 tmp2[CHAN_CNT_SIZE];
	 I32 sig_few                     = 0;
	 UI8 tmpval;

     FILE *fpRead;    
     fpRead = popen(SCAN_WIFI, "r");    
        
     for(i=0;i < CHAN_CNT_SIZE;i++) 
		 chans_signal[i] = -500;

	 memset(buf,'\0',sizeof(buf));    
	 while(fgets(buf,MAX_BUF_CACHE - 1,fpRead) != NULL)
	 {   
        #if 0
        printf("tmp1 buf=%s\n",buf);
		#endif
	
		retval       = find_substring(buf,"Channel:");
		if(retval < 0 ) continue;
		tmp_chan     = atoi(buf + retval + 8);
        
		if(fgets(buf,MAX_BUF_CACHE - 1,fpRead) == NULL) continue;

        #if 0
		printf("tmp2 buf=%s\n",buf);
		#endif
			
		retval       = find_substring(buf,"Signal:");
		if(retval < 0) continue;

		tmp_sig      = atoi(buf + retval + 8);

		#if 0
	    printf("tmp_sig=%d\n",tmp_sig);
		#endif

        #if 0
        printf("tmp_chan=%d\ttmp_sig=%d\n",tmp_chan,tmp_sig);
        #endif

		switch(tmp_chan)
		{
             case 36:
				   chans_cnt[0]++;
                   if(chans_signal[0] < tmp_sig)
					   chans_signal[0] = tmp_sig;
				   break;
			  case 40:
				   chans_cnt[1]++;
                   if(chans_signal[1] < tmp_sig)
					   chans_signal[1] = tmp_sig;
				   break;
			  case 44:
				   chans_cnt[2]++;
                   if(chans_signal[2] < tmp_sig)
					   chans_signal[2] = tmp_sig;
				   break;
			  case 48:
				   chans_cnt[3]++;
                   if(chans_signal[3] < tmp_sig)
					   chans_signal[3] = tmp_sig;
				   break;
			  case 149:
				   chans_cnt[4]++;
				   if(chans_signal[4] < tmp_sig)
					   chans_signal[4] = tmp_sig;
				   break;
			  case 153:
				   chans_cnt[5]++;
			       if(chans_signal[5] < tmp_sig)
					  chans_signal[5] = tmp_sig;
				   break;
			  case 157:
				   chans_cnt[6]++;
			       if(chans_signal[6] < tmp_sig)
					  chans_signal[6] = tmp_sig;
				   break;
			  case 161:
				   chans_cnt[7]++;
			       if(chans_signal[7] < tmp_sig)
					  chans_signal[7] = tmp_sig;
				   break;
              case 165:
                   chans_cnt[8]++;
			       if(chans_signal[8] < tmp_sig)
					  chans_signal[8] = tmp_sig;
                   break;
		  }
	 }
	 

	 if(fpRead!=NULL)        
	 	pclose(fpRead);  

     
#if 0
     for(i=0;i < CHAN_CNT_SIZE;i++)
     {
        printf("channel %d=%d\t maxsig=%d\n",chan_arrays_support[i],chans_cnt[i],chans_signal[i]);
     } 
#endif	 
     
     //最少占用信道统计
     chans_few = chans_cnt[0];

     for(i=0;i < CHAN_CNT_SIZE;i++)
	 {
        if(chans_few > chans_cnt[i]){
			chans_few = chans_cnt[i];
		}
	 }

	 for(i=0,j=0;i < CHAN_CNT_SIZE;i++)
	 {
        if(chans_cnt[i] == chans_few){
            tmp[j++] = i;
		}
	 }


	 //最少占用信道中信号强度最弱统计
	 sig_few = chans_signal[0]; 
	 for(i=0;i < j;i++)
	 {
		tmpval = tmp[i];
		if(sig_few > chans_signal[tmpval])
			sig_few = chans_signal[tmpval];
	 }
     
     for(i=0,k=0;i < j;i++)
	 {
		tmpval = tmp[i];
		if(chans_signal[tmpval] == sig_few)
			tmp2[k++] = tmpval;
     }

	 return chan_arrays_support[tmp2[rand() % k]];	  
}




I32  main(I32 argc,I8*argv[])
{
	UI8 is_effect = 1;
	UI8 chan      = 0;

    srand(time(NULL));

    if(argc > 1)
	{
	   //随机信道只提交下次生效
       if(!strcmp("commit",argv[1]) ||
		!strcmp("COMMIT",argv[1]))
	   {
		   chan_commit();

		   return 0;
	   }
	   //自动选择最优信道
	   else if(!strcmp("auto",argv[1]) ||
		!strcmp("AUTO",argv[1]))
	   {
		   is_effect = 0;
		   chan      = chan_auto();
	   }
       //指定具体信道
	   else if(!strcmp("-c",argv[1]) ||
		!strcmp("-C",argv[1]))
	   {
           chan = atoi(argv[2]);
	   }
	}
	else
	{
      sleep(1);
	}

	chan_switch(is_effect,chan);

    return 0;
}

执行交叉编译

GCC=/home/openwrt-master/staging_dir/toolchain-mips_74kc_gcc-5.3.0_musl-1.1.16/bin/mips-openwrt-linux-gcc
$GCC chan_switch.c -o chan_switch -O2 -w

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值