STM32+M5311对接 OneNET 项目记录

2023-11-16

以前做过的一个演示项目,一款判断人体进出的语言播报方案,通过LwM2M 协议连接 OneNET :
硬件平台:M5311 + STM32F103
云平台:中国移动 OneNET
语音芯片:WT(唯创知音) WT588D
传感器探头:  SHARP(夏普)  GP2Y0A21YK0F 
文章意在于对本次项目做个笔记,方便以后再次用到。

前言

本文是个人笔记,文章只讲基本流程,不讲细节,因为时间太久了,也不太记得了= =!只是个人笔记……

最后所有的资料原理图和程序都会上传至资源。

一、硬件部分

整个项目硬件本相对来说是最简单的,硬件设计可以参考《M5311硬件设计手册》,下面上一下各部分原理图,因为本文主要记录的是 M5311 的使用,STM32我就当大家都很熟悉了,上个最小系统,然后语音模块WT588D 芯片:

1.1 M5311芯片部分

在这里插入图片描述

1.2 SIM 卡部分

在这里插入图片描述

1.3 控制与指示部分

在这里插入图片描述

1.4 STM32部分

在这里插入图片描述

1.5 WT588D部分

在这里插入图片描述

1.6 功放部分

在这里插入图片描述

1.7 电源部分

在这里插入图片描述
其他的细节图这里就不上了,只要把主要的这几个地方设计好,其他的地方是很简单的。

二、对接流程

一般来说,对于开发者,这种对接流程是整个工程中相对比较复杂的。

但是中移动官方已经给我们提供了详细的说明文档:《M531X_OneNET参考手册》,因为模块是中移动的,云平台也是中移动的,所以对接资料还是很到位的,这里我只做个简单总结:

2.1 整理流程图

在这里插入图片描述

2.2 注册码

一般来说都是对接重庆的平台,M5311直接使用这个码就可以:

/*设置模组侧设备注册码*/
char* Onenet_key = "AT+MIPLCREATE=56,130038F10003F2002A04001100000000000010196E\
62696F7462742E6865636C6F7564732E636F6D3A35363833000131F300080000000000,0,56,0\r\n";//设置模组侧设备注册码

2.3 OneNeT 指令集接入汇总

说明部分截取文档中的说明:
在这里插入图片描述在这里插入图片描述

2.3.1 资源说明

对于上面的 Object 3200 资源对应关系,有一个表格(下面只列出了部分),在上传资源《资源表》文档有完整的说明:
在这里插入图片描述

在这里插入图片描述在这里插入图片描述在这里插入图片描述如果设备超过了保活时间就会离线,此时无法发送消息,需要重新上线,但是不需要再进行注册码登记了,直接发送资源配置与登录即可,保活时间单位为s

三、软件部分

本项目的重点就在于 M5311 的驱动部分,解决了 M5311 的驱动,其他基本没有问题。

3.1 基本定义

M5311 的驱动需要根据文档的说明来,首先我们得根据自己的需求做一个初始的定义:
在这里插入图片描述

3.2 AT命令发送函数

其次实现 AT 指令发送的函数:
在这里插入图片描述

3.3 M5311初始化函数

初始化函数中除了对模块的复位操作,还有重要的地方就是获取 SIM 卡的 IMEI 和 IMSI,这个在后面平台添加设备的时候需要填写 SIM 卡的这两个参数。

初始化函数如下图:
在这里插入图片描述

其他的地方直接看下面源代码把。

虽然所有资料我会上传至资料,但是还要积分下载,这里我把本项目核心的 M5311 驱动部分代码直接贴上,需要的小伙伴直接看这个就行了

/******
* 
正常程序中等待返回指令,不能死等,如果设备没有插卡或者卡不正常,就永远启动不了,
进入不了正常的门禁程序
每个步骤使用函数定义,每个步骤规定尝试次数,使用if判断 即便失败,也能够进入正常程序

2020/2/18
模组侧 OneNET 数据收发流程
序列  命令  描述
1   AT+MIPLNOTIFY=0,0,3200,0,5750,1,4,"abcd",0,0,147    数据上传
2   AT+MIPLREADRSP=0,32705,1,3200,0,5750,1,4,"abcd",0,0  Read 操作回复
3   AT+MIPLWRITERSP=0,25845,2                            Write 操作回复
4   AT+MIPLEXECUTERSP=0,18166,2                          Execute 操作回复

data type
1 string  2 opaque  3  integer  4 float   5 bool

+MIPLNOTIFY Example
AT+MIPLNOTIFY=0,1477,3202,0,5600,4,3,"1.2",0,0,35
OK
+MIPLEVENT:0,26,35
AT+MIPLNOTIFY=0,1478,3202,2,5600,4,5,"-0.08",2,1
OK
AT+MIPLNOTIFY=0,1478,3202,2,5601,4,3,"-0.08",1,2
OK
AT+MIPLNOTIFY=0,1478,3202,2,5602,4,5,"-0.08",0,0
OK
4.6.9. AT+MIPLREADRSP

+MIPLREADRSP Example
+MIPLREAD:0,289,3200,0,5750
AT+MIPLREADRSP=0,289,1,3202,0,5750,1,5,"-0.08",0,0    //"-0.08前面是长度",5    再前面2个是数据类型  1
OK

示例
+MIPLREAD:<ref>,<mid>,<objid>,<insid>,<resid>
参数说明
<ref> 
OneNET 设备实例 ID。
<mid> 
消息 ID。
<objid>
Object ID。
<insid>
Instance ID,如果为-1,需要读取该 object 下的所有资源。
<resid>
Resource ID,如果为-1,需要读取该 instance 下的所有资源。

+MIPLREAD:0,18172,3200,0,5750
AT+MIPLREADRSP=0,18172,11       //错误读取
OK
+MIPLREAD:0,18172,3200,0,-1     
AT+MIPLREADRSP=0,18172,1,3200,0,5500,5,1,"0",2,1        //最后一个1,第一条报文
OK
AT+MIPLREADRSP=0,18172,1,3200,0,5501,3,3,"-12",1,2      //最后一个为2,中间报文
OK
AT+MIPLREADRSP=0,18172,1,3200,0,5750,1,4,"test",0,0     //最后一个为0,最后一条报文
OK

+MIPLWRITERSP Example
+MIPLWRITE:0,321,3200,0,5750,1,3,123,0
AT+MIPLWRITERSP=0,321,2
OK

2020/2/19
AT+MIPLDISCOVERRSP
该命令用于设置指定 object 的所需资源列表。
举例:
/
查表可得:此处设定 数字输入 3个资源列表:1、数字输入状态  2、数字输入计数器  3、应用类型
/
AT+MIPLDISCOVERRSP=0,3200,1,14,”5500;5501;5750” 
OK

说明:设备注册时间例程为 3000S,时间范围为 有符号的 4字节整形  [-2147483648, 2147483647];
建议设置为一两天,快到时间更新
:
模组侧设备存活时间更新流程
序列  命令  描述
AT+MIPLUPDATE=0,3000,0       //存活时间更新流程,继续存活3000S


******/
#include"common.h"


// typedef enum
// {
// 	//! Waiting for the synchronisation  +MIPLxxxx
// 	GET_SYNC_STATE=0,   
// 	//! 
// 	GET_ref_STATE,
// 	//! 
// 	GET_mid_STATE,
// 	//! 
// 	GET_objid_STATE,
//     //!
//     GET_insid_STATE,
//     GET_resid_STATE
// } STATES_GET_PACKET; 


char* AT = "AT";
char* AT_RST = "AT+CMRB";
char* IMEI = "AT+GSN";
char* IMSI = "AT+CIMI";
char* Open_led = "AT+CMSYSCTRL=0,2";
char* Close_sleep = "AT+SM=LOCK_FOREVER";
// char* RSSI = "AT+CSQ";
// char* CEREG = "AT+CEREG?";
char RSSI[] = "AT+CSQ";
char CEREG[] = "AT+CEREG?";
/*设置模组侧设备注册码*/
char* Onenet_key = "AT+MIPLCREATE=56,130038F10003F2002A04001100000000000010196E\
62696F7462742E6865636C6F7564732E636F6D3A35363833000131F300080000000000,0,56,0\r\n";//设置模组侧设备注册码
char* LWM_object_T = "AT+MIPLADDOBJ=0,3303,1,\"1\",0,1";  //订阅 Object 3303 资源设置
char* LWM_Resource_T = "AT+MIPLDISCOVERRSP=0,3303,1,4,\"5700\"";//订阅 Resource 5700 资源设置  
char* LWM_object_H = "AT+MIPLADDOBJ=0,3304,1,\"1\",0,1";//订阅 Object 3304 资源设置
char* LWM_Resource_H = "AT+MIPLDISCOVERRSP=0,3304,1,4,\"5700\""; //订阅 Resource 5700 资源设置
char* Onenet_connect = "AT+MIPLOPEN=0,65000,30"; //设备登录到 OneNET 平台,一天为86400秒,16位 65535 ,定时65000S,到64500时间更新
char LWM_object_Pir[] = "AT+MIPLADDOBJ=0,3300,1,\"1\",0,0";         //3300通用传感器
char LWM_Resource_Pir[] = "AT+MIPLDISCOVERRSP=0,3303,1,4,\"5502\"";//订阅 Resource 5502 资源设置 ,bool类型,分别对应进出

char* Time_refresh = "AT+MIPLUPDATE=0,65000,0"; //平台时间更新
char* T_begin= "AT+MIPLNOTIFY=0,0,3303,0,5700,4,4,\"";
char* T_end = "\",0,0";


void T_Send_Test(u8 t_data){
    char Send_onenet_T[50] = ""; 
    sprintf(Send_onenet_T,"AT+MIPLNOTIFY=0,0,3303,0,5700,4,4,\"%d\",0,0",t_data); 
    Iot_SendCmd(Send_onenet_T,"OK",1000);   
}


/*******************************************************************************
  发送字符串  并解析返回值是否正确
  cmd为传入值  reply 为校验返回值 wait 为延时
*******************************************************************************/
int Iot_SendCmd(char* cmd, char* reply, int wait)
{
	u8 i;
    memset(&struct_usart3.USART_BUFF, 0, sizeof(struct_usart3.USART_BUFF)); //先清空缓冲区
    struct_usart3.USART_Length = 0;
    printf("[NBiot_SendCmd] %s\r\n 等待时间 %d ms\r\n", cmd,wait);
    delay_ms(100);
    uart3_send_buff((u8*)cmd,strlen(cmd));
    if (wait >= 1000){
        for (i = 0; i < (wait / 1000); i++){
            delay_ms(1000);
        }
    }
    else delay_ms(wait);

    if(strcmp(reply , "") == 0) return 0 ; // 返回值为空
    if (struct_usart3.USART_Length != 0){
        if (strstr((char*)struct_usart3.USART_BUFF, reply)){
            printf("\r\n%s\r\n", struct_usart3.USART_BUFF);
            return 1;
        }
        else if (strstr((char*)struct_usart3.USART_BUFF, "ERROR")){
            printf("ERROR...\r\n");
            return 0;
        }
        else{
            printf("\r\n%s\r\n", struct_usart3.USART_BUFF);
            return 0;
        }
    }
    return 0 ;  
}

void Iot_SendNOCheck(char* cmd)
{
    uart3_send_buff((u8*)cmd,strlen(cmd));
}

void m5311_on(void)
{
    //硬件复位
    GPIO_SetBits(GPIOB,GPIO_Pin_7);
    delay_ms(1200);
    GPIO_ResetBits(GPIOB,GPIO_Pin_7);
    delay_ms(200);
}

/**************
 * 重启模块
 *************/

/**************
 * 重启模块,如果失败,尝试3次
 *************/
int Rst_mode()
{
	int res = 0 ;
	int i = 0;
    for(i=0;i<4;i++){
	    res = Iot_SendCmd(AT_RST,"READY",3000);
        if(res == 1) return res;
    }	
	return res ; 
}

/**************
 * AT,如果失败,尝试3次
 *************/
int AT_OK() 
{
	int res = 0 ;
	int i = 0;
    for(i=0;i<4;i++){
	    res = Iot_SendCmd(AT,"OK",1000);
        if(res == 1) return res;
    }	
	return res ; 
}

/**************
 * 关闭睡眠,如果失败,尝试3次
 *************/
int Closesleep_mode() 
{
	int res = 0 ;
	int i = 0;
    for(i=0;i<4;i++){
	    res = Iot_SendCmd(Close_sleep,"OK",1000);
        if(res == 1) return res;
    }	
	return res ; 
}

int Check_CEREG() 
{
	int res = 0 ;
	int i = 0;
    for(i=0;i<6;i++){
	    res = Iot_SendCmd(CEREG,"1",1500);
        if(res == 1) return res;
    }	
	return res ; 
}

/**************
 * Onenet注册码 ,如果失败,尝试3次
 *************/
int Onenet_create()
{
    int res = 0 ;
	int i = 0;
    for(i=0;i<4;i++){
	    res = Iot_SendCmd(Onenet_key,"+MIP",1500);
        if(res == 1) return res;
    }	
	return res ;   
}

/*
订阅Object,LWM2M协议标准 
*/
int Lwm2m_object_Pir()
{
    int res = 0 ;
	int i = 0;
    for(i=0;i<4;i++){
	    res = Iot_SendCmd(LWM_object_Pir,"OK",1000);
        if(res == 1) return res;
    }	
	return res ;     
}


int Lwm2m_object_T()
{
    int res = 0 ;
	int i = 0;
    for(i=0;i<4;i++){
	    res = Iot_SendCmd(LWM_object_T,"OK",1000);
        if(res == 1) return res;
    }	
	return res ;     
}

int Lwm2m_object_H()
{
    int res = 0 ;
	int i = 0;
    for(i=0;i<4;i++){
	    res = Iot_SendCmd(LWM_object_H,"OK",1000);
        if(res == 1) return res;
    }	
	return res ;     
}

/*
订阅Resource
*/

int Lwm2m_resource_Pir()
{
    int res = 0 ;
	int i = 0;
    for(i=0;i<4;i++){
	    res = Iot_SendCmd(LWM_Resource_Pir,"OK",1000);
        if(res == 1) return res;
    }	
	return res ;     
}

int Lwm2m_resource_T()
{
    int res = 0 ;
	int i = 0;
    for(i=0;i<4;i++){
	    res = Iot_SendCmd(LWM_Resource_T,"OK",1000);
        if(res == 1) return res;
    }	
	return res ;     
}

int Lwm2m_resource_H()
{
    int res = 0 ;
	int i = 0;
    for(i=0;i<4;i++){
	    res = Iot_SendCmd(LWM_Resource_H,"OK",1000);
        if(res == 1) return res;
    }	
	return res ;     
}

/**************
 * Onenet登录 ,如果失败,尝试3次
 *************/
int Onenet_sign_in()
{
    int res = 0 ;
	int i = 0;
    for(i=0;i<4;i++){
	    res = Iot_SendCmd(Onenet_connect,"OK",1000); //测试查看返回结果再确定如何使用
        if(res == 1) return res;
    }	
	return res ;   
}


int Onenet_time_refresh()
{
    int res = 0 ;
	int i = 0;
    for(i=0;i<4;i++){
	    res = Iot_SendCmd(Time_refresh,"OK",1000); //测试查看返回结果再确定如何使用
        if(res == 1) return res;
    }	
	return res ;   
}

/*
采用这种逻辑,产品不会因为NB网络问题导致,正常的门禁播报不能实现
*/
#ifdef TTEST
void m5311_init(void)
{
    m5311_on();   
}
#else
void m5311_init(void)
{
    m5311_on();
    printf("等待软复位……\r\n");
    if(Rst_mode()){
        if(AT_OK()){
            printf("复位成功……,AT指令测试成功,打开LED指示灯\r\n");
            Iot_SendCmd(Open_led, "OK", 1000);//打开LED指示灯,正常程序不需要
            if(Closesleep_mode()){
                printf("关闭睡眠模式,查询NB卡的IMEI和IMSI\r\n");
                Iot_SendCmd(IMEI,"OK", 1000);  //获取IMEI
                Iot_SendCmd(IMSI,"OK", 1000);  //获取IMSI 
                printf("查看信号质量\r\n");
                if(Check_CEREG()){
                    printf("信号正常,一切准备就绪\r\n");  
                }  
            }
        }
    }
}
#endif
/*****
  onenet 连接
  while (!Send_NBIOT(Onenet_key, "+MIP", 500));   //这个消息经常返回出错,原因不明。
  while (!Send_NBIOT(LWM_object_T, "OK", 1000));
  while (!Send_NBIOT(LWM_Resource_T, "OK", 1000));
  while (!Send_NBIOT(LWM_object_H, "OK", 1000));
  while (!Send_NBIOT(LWM_Resource_H, "OK", 1000));
  while (!Send_NBIOT(Onenet_connect, "OK", 1000));
  Serial.println("Connect_onenet!!!");

  *******/
#ifdef TTEST
void onenet_init(void)
{
    printf("开始测试……,请手动输入指令\r\n");       
}
#else
void onenet_init()
{
    printf("开始创建设备,如果创建过,返回错误也没关系,直接跳过这一步\r\n");
    Onenet_create(); 
    Lwm2m_object_Pir();
    Lwm2m_resource_Pir();
        if(Onenet_sign_in()){
            printf("ONENET 登录成功!\r\n");   
        }
        else;
    Onenet_ON = TRUE;  //这里不好判断是不是真的连接上了,所以初始化以后目前都认为是连接上了
}
#endif

/*

    数据处理

    缓存数据处理判断先测试一下,空闲标志位 = 1时候处理,
    再测试 长度 部位0 情况处理。

    有一个问题,就是缓存什么时候清空,应该是判断完了以后就清空,要不人随时可能来数据,冲乱数据位

    void T_Send_Test(u8 t_data){
    char Send_onenet_T[50] = ""; 
    sprintf(Send_onenet_T,"AT+MIPLNOTIFY=0,0,3303,0,5700,4,4,\"%d\",0,0",t_data); 
    Iot_SendCmd(Send_onenet_T,"OK",1000);   
}

*/
void EXECUTER_back(char *cmd)
{
    char Send_EXECUTER_back[50] = "";  
    sprintf(Send_EXECUTER_back,"AT+MIPLEXECUTERSP=0,%s,2",cmd); 
    Iot_SendNOCheck(Send_EXECUTER_back); 
    printf("%s\r\n",Send_EXECUTER_back);   
}

void call_back()
{
    u8 i = 0;
    u8 j = 0;
    u8 u8Count  =0;
    char msg[10] = {0};
    if(struct_usart3.flag == 1){
        printf("收到服务器数据:%s \r\n",struct_usart3.USART_BUFF);       
        if (strstr((char*)struct_usart3.USART_BUFF, "+MIPLEXECUTE")){
            printf("指令数据……\r\n");
            if(strstr((char*)struct_usart3.USART_BUFF, "chone")){command_on = TRUE;command = 1;}
            else if(strstr((char*)struct_usart3.USART_BUFF, "chtwo")){command_on = TRUE;command = 2;}
            else if(strstr((char*)struct_usart3.USART_BUFF, "chthree")){command_on = TRUE;command = 3;}
            else if(strstr((char*)struct_usart3.USART_BUFF, "chfour")){command_on = TRUE;command = 4;}
            else if(strstr((char*)struct_usart3.USART_BUFF, "chfive")){command_on = TRUE;command = 5;}
            else if(strstr((char*)struct_usart3.USART_BUFF, "chsix")){command_on = TRUE;command = 6;} 
            else if(strstr((char*)struct_usart3.USART_BUFF, "chseven")){command_on = TRUE;command = 7;}
            else if(strstr((char*)struct_usart3.USART_BUFF, "cheight")){command_on = TRUE;command = 8;}
            else if(strstr((char*)struct_usart3.USART_BUFF, "chnine")){command_on = TRUE;command = 9;}
            else if(strstr((char*)struct_usart3.USART_BUFF, "chten")){command_on = TRUE;command = 10;}
            else;
            //+MIPLREAD:0,289,3200,0,5750  
            //AT+MIPLREADRSP=0,32705,1,3200,0,5750,1,4,"abcd",0,0  Read 操作回复,
            //+MIPLEXECUTE:0,51638,3301,0,5601,4,"ping"
            //AT+MIPLEXECUTERSP=<ref>,<msgid>,<result>
            //AT+MIPLEXECUTERSP=0,51638,2
            for(i=0;i<strlen(struct_usart3.USART_BUFF);i++){
                if((char)struct_usart3.USART_BUFF[i] == ':') break;             
            }
            i++;//0
            i++;//,
            i++;//数字第一位,这里如果不继续加一位,下面的for会直接跳出,因为第一个if就是','
            u8Count =i;
            for(;i<(strlen(struct_usart3.USART_BUFF)-u8Count);i++){
                if((char)struct_usart3.USART_BUFF[i] != ','){
                    msg[j++] = struct_usart3.USART_BUFF[i];
                }
                else break;
            } 

            printf("指令回复……\r\n");    
            EXECUTER_back(msg);
            printf("指令回复完毕……\r\n"); 

        }
        else if(strstr((char*)struct_usart3.USART_BUFF, "+MIPLWRITE")){
            printf("写数据……\r\n");
        }
        else if(strstr((char*)struct_usart3.USART_BUFF, "+MIPLREAD")){
            printf("读数据……\r\n");
        }
        else printf("不需要的数据\r\n");
        printf("清楚缓存……\r\n");
        struct_usart3.flag = 0;
        struct_usart3.USART_Length = 0;
        memset(&struct_usart3.USART_BUFF, 0, sizeof(struct_usart3.USART_BUFF)); //清空缓冲区    
    }    
}

四、云平台部分

云平台设置部分,使用截图演示一遍。

4.1 创建添加产品

在 OneNET 主界面右上角 进入控制台 界面,选择NB-IoT物联网套件,如图:
在这里插入图片描述

进入NB-IoT物联网套件页面以后,如果以前有产品会有产品列表:
在这里插入图片描述
这里我们点击添加产品:
在这里插入图片描述

4.2 添加设备

点击需要添加设备的产品进行添加设备,按如下操作:
在这里插入图片描述

这里填写的 IMEI 和 IMSI 是根据上文 3.3 M5311初始化函数获取到的,新的 SIM卡添加设备需要在 第一次上电的时候查看一下这两个参数:

在这里插入图片描述

这里我就不添加了,直接用以前的设备做个展示:

在这里插入图片描述
添加好了设备以后模块通过我们的正常流程就能与 OneNET 交互信息了,里面的一些详情和资源可以自己研究查看一下,比如资源属性:
在这里插入图片描述

这个5502是和 2.3.1 资源说明 一样的,属性意义在《资源表》文档中有说明:
在这里插入图片描述

本片记录就到这里,需要全部资源的小伙伴可以去下载,或者直接找我要也可以!

资源链接:STM32+ M5311连接OneNET方案原理图,源码,参考资料

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

STM32+M5311对接 OneNET 项目记录 的相关文章

  • 医院RFID药物跟踪管理解决方案

    1 技术背景 基于 2018年2月6日 药物调配商QuVa Pharma 与Kit Check合作 为其医院药房客户 提供基于RFID药物跟踪管理解决方案 QuVa提供的系统包括Kit Check的 无源 超高频 UHF RFID 标签 该
  • WEB基础-变形动画

    字体图标 IconFont 图标字体也叫字体图标 就是字体做的图标 可以通过设置字体的方式改变图标的样式 受到近些年 扁平化设计 的影响 越来越多的图标都开始使用 IconFont 下载字体图标 首先打开IconFont 阿里巴巴矢量图标库
  • websocket详解

    之前利用websocket以及jQuery做了一个聊天通讯应用 最近在总结整个过程中的一些问题 也借此机会聊聊websocket协议 webSocket本身不存在跨域问题 所以可以利用webSocket来进行非同源之间的通信 webSock
  • pytorch打印模型梯度

    简介 有时候在调试模型训练过程时 我们需要打印模型中参数的梯度 去查看是否存在梯度消失或者梯度爆炸的问题 可以通过在backward之后查看params的grad属性来确认 参考代码如下所示 import torch 定义模型 class
  • Python3 面向对象编程

    好记性不如烂笔头 对之前阅读书籍进行梳理与总结 此文为 Python3面向对象编程 阅读笔记 文章目录 第一章 面向对象设计 第二章 Python对象 第三章 对象相似时 第四章 异常捕获 第五章 何时使用面向对象编程 第六章 Python
  • C# 导出 Excel 方法

    第一种 使用 Microsoft Office Interop Excel dll public void ExportExcel DataTable dt if dt null Microsoft Office Interop Excel

随机推荐

  • 关键词生成器在线-在线免费关键词生成器

    关键词生成 什么是关键词生成 关键词生成就是根据你输入的一个关键词生成成千上百的核心关键词 围绕着你输入的核心词来生成的 优先生成大量用户搜索的关键词 今天就给大家分享一款免费关键词生成工具 关键词生成的来源主要是用户都在搜索的词 相关搜索
  • CentOS-8-x86_64-1905安装

    CentOS 8 x86 64 1905安装 安装前准备 VMware Workstation 点击下载虚拟机软件 VMware Workstation是一款功能强大的桌面虚拟计算机软件 提供用户可在单一的桌面上同时运行不同的操作系统 和进
  • Crazy Thairs【树状数组+高精度+DP思想】

    题目链接 POJ 3378 题意 有N个点 问的是要求组成一个长度为5的上升子序列的组成有多少种 最搞事情的是这道题不用取模 所以 是一定会爆long long的 首先 很容易想到一点就是我们可以开一个dp maxN 5 表示的是 dp i
  • Vagrant学习笔记:搭建K8s集群

    通常情况下 我们在使用VMware VirtualBox这一类虚拟机软件创建虚拟开发环境时 往往需要经历寻找并下载操作系统的安装镜像文件 然后根据该镜像文件启动的安装向导一步一步地安装与配置操作系统 最后还需要从零开始安装开发与运维工具 整
  • 计算机考研复试机试怎么速成,西安电子大学计算机考研复试机试(2019)+ 学长讲解(6)+ 作业...

    学长讲的就是算法笔记的入门算法 作业1 链接 https www nowcoder com questionTerminal 0f64518fea254c0187ccf0ea05019672 来源 牛客网 有一个网络日志 记录了网络中计算任
  • Java各种集合判空总结

    目录 集合判空 CollectionUtils isEmpty推荐 原始判断 isEmpty 其他 数组判空 集合判空 CollectionUtils isEmpty推荐 这个使用到了spring的工具类 需要提前引入依赖 import o
  • 机器学习2018-12-28

    机器学习 组成 主要任务 分类 classification 将实例数据划分到合适的类别中 应用实例 判断网站是否被黑客入侵 二分类 手写数字的自动识别 多分类 回归 regression 主要用于预测数值型数据 应用实例 股价价格波动的预
  • 用编程器免拆夹子刷斐讯K2 K2P解决难搞固件 刷BREED 无损原EEPROM

    文章中放的几个地址都是思路来源 感谢各路大神原帖子的思路 因为我刷机时候没有拍照 只好借用各位大佬的图来说明步骤 我做一下整理会放出本篇刷机流程 很简单 K2 22 6 532 231软件版本已经无解 UBOOT等可以软刷的方式都被堵死 编
  • .NET编程——利用C#实现TCP协议的异步通信Socket套接字(WinForm)

    本文将介绍利用基于TCP通信协议的Socket实现服务器与客户端之间的数据传输 目录 前言 计算机通信 创建服务器 服务器通信 创建客户端 客户端通信 前言 TCP IP Transmission Control Protocol Inte
  • 【编码-校验码】奇偶校验码

    https zhuanlan zhihu com p 26509678 引自原文 1 定义 奇偶校验位 英语 Parity bit 或校验比特 check bit 是一个表示给定位数的二进制数中1的个数是奇数还是偶数的二进制数 奇偶校验位是
  • 炫酷的Android智能下拉刷新框架,值得一看

    1 Android智能下拉刷新框架 SmartRefreshLayout 支持所有的 View AbsListView RecyclerView WebView View 和多层嵌套的视图结构 支持自定义并且已经集成了很多炫酷的 Heade
  • BRDF详解

    光照模型主要分为三类 测量模型 经验模型和基于物理的分析模型 在计算机图形学中介绍的光照模型为经验模型中的Phong模型 也就是本人理解的 根据点距光源的位置 入射角度等信息计算的 反射强度 包括漫反射强度 镜面反射强度 但是Phong模型
  • 《effective c++》笔记

    序 1 object 在 object oriented技术中的真正意义是 物件 物体 而非 对象 目标 导读 1 术语 1 声明式 告诉编译器名称和类型 但略去细节 std size t numDigit int number std命名
  • 软工导论知识框架(六)面向对象分析

    前言 绘制各种类型的图是重点 对于面向对象建模中需要绘制的图总结在第五期中 软工导论知识框架 五 面向对象方法学 一 分析过程 1 获取需求 与用户交谈 向用户提问题 参观用户的工作流程 观察用户的操作 向用户群体发调查问卷 与同行 专家交
  • 【满分】【华为OD机试真题2023 JAVA&JS】查找重复代码

    华为OD机试真题 2023年度机试题库全覆盖 刷题指南点这里 查找重复代码 时间限制 1s 空间限制 32MB 限定语言 不限 题目描述 小明负责维护项目下的代码 需要查找出重复代码 用以支撑后续的代码优化 请你帮助小明找出重复的代码 重复
  • 使用IntelliJ IDEA查看类的继承关系图形

    最近正好也没什么可忙的 就回过头来鼓捣过去的知识点 到Servlet部分时 以前学习的时候硬是把从上到下的继承关系和接口实现记得乱七八糟 这次利用了IDEA的diagram 结果一目了然 也是好用到炸裂 就此分享 1 查看图形形式的继承链
  • Golang基础 流程控制 条件判断

    条件判断 01 条件判断 if 02 分支选择 switch 03 异步处理 select 参考资料 条件语句一般指定一个或多个条件 并通过测试条件是否为 true 来决定是否执行指定语句 并在条件为 false 的情况在执行另外的语句 0
  • 你得学会并且学得会的Socket编程基础知识

    这一篇文章 我将图文并茂地介绍Socket编程的基础知识 我相信 如果你按照步骤做完实验 一定可以对Socket编程有更好地理解 本文源代码 可以通过这里下载 http files cnblogs com chenxizhang Socke
  • xLua游戏中的热更新(基于Unity2018)

    什么是热更新 热 就是刚出炉 简单来说就是当游戏某个功能出现bug 或者修改了某个功能 或者增加了某个功能的时候 我们不需要重新下载安装安装包 就可以更新游戏内容 热更新的好处 不用浪费流量重新下载 不用通过商店审核更加快速 不用重新安装玩
  • STM32+M5311对接 OneNET 项目记录

    以前做过的一个演示项目 一款判断人体进出的语言播报方案 通过LwM2M 协议连接 OneNET 硬件平台 M5311 STM32F103 云平台 中国移动 OneNET 语音芯片 WT 唯创知音 WT588D 传感器探头 SHARP 夏普