STM32 lorawan trasplante de nodo de conexión de protocolo cosas Tencent plataforma de desarrollo de las nubes (IO Explorer)

STM32 pila lorawan trasplante de cosas conectadas plataforma de desarrollo de Tencent nube (IO Explorer)

prefacio

Antes de protocolo de trasplante, nos dan acerca de la diferencia entre la ciencia y lorawan de Lora.

LoRa LPWAN es una tecnología de comunicación, la adopción de los Estados Unidos y promover Semtech un esquema de transmisión inalámbrica de larga distancia basada en la tecnología de espectro ensanchado. Este esquema convencional se cambia en la forma de un compromiso con la transmisión de potencia por parte del usuario para proporcionar un sistema más simple puede lograr a larga distancia, batería de larga duración, de gran capacidad, y las redes de sensores y luego extendidas. Actualmente, LoRa principales bandas de frecuencia libre globales y diversos países y regiones no son los mismos, China se está ejecutando en el área 470MHz y 779MHZ.

LoRaWAN es un estándar abierto que define una tecnología de chip LPWAN LoRa basado protocolo de comunicación. LoRaWAN define en el enlace de datos de control de acceso a medios de capa (el MAC), diseñado para un solo operador de red diseñado para grandes público, específicamente, cada nodo transmite los datos a la puerta de enlace o más puertas de enlace. La puerta de enlace reenvía los datos a un servidor de red, cheque lleva a cabo la redundancia, control de seguridad, y el horario de mensajes en un servidor de red, LoRaWAN Unión y ahora mantenidos por Lora ( Enlace ).

En general, el protocolo de capa de enlace comprende Lora solamente, y es muy adecuado para la comunicación P2P entre los nodos, al mismo tiempo, el módulo de Lora (Li Chong el centro comercial sobre 20) que LoRaWAN (un tesoro 30-40) más barato;
LoRaWAN que comprende la capa de red, es posible enviar información a la estación base conectada a cualquier plataforma en la nube. Sólo la antena correcta está conectado a su salida, el módulo de LoRaWAN puede funcionar a diferentes frecuencias.

Aquí Insertar imagen Descripción
una imagen gana thoustands palabras (que se muestra en la figura.)
LoRaWAN = la capa MAC
Lora = a la capa PHY
Lora + = LPWAN LoRaWAN

Es a causa de la creación de redes lorawan, miles de nodos se hace posible, esta vez la puerta de enlace trasplante STM32 conectado nodos (SX1301) se puede conectar teóricamente 62500 nodos.

entorno de desarrollo listo

Nucleo-F746ZG Junta y ST Nucleo LoRa Módulo GW debajo de
Aquí Insertar imagen Descripción
núcleo-L073R8 Junta y ST Nucleo LoRa sensor V2
Aquí Insertar imagen Descripción
porque módulo RHF0M003 en ST Nucleo LoRa sensor V2 ha integrado el protocolo lorawan, la MCU sólo tiene que enviar comandos AT se puede realizar mediante UART lorawan comunicaciones (una más cara por encima de dicho módulo de clase)

Shun puede ra-02 (sx1278)
Aquí Insertar imagen Descripción
módulo de placa de conexión desarrollado por línea de Dupont SPI1 GPIO (pin PA0-reset, PA10- pin de interrupción), el VCC y tierra, conectado como se muestra a continuación:
Aquí Insertar imagen Descripción
el PC a través de una puerta de enlace de conexión en serie, a través de comandos AT cosas conectados plataforma de desarrollo Tencent nube, la instrucción siguiente
el AT + PKTFWD = loragw.things.qcloud.com, 1700,1700
el AT CH + = 0,486.3, A
la AT CH + = 1,486.5, A
la AT CH + = 2,486.7, A
la AT + CH = 3,486.9, A
la AT + CH = 4,487.1, B
la AT + CH = 5,487.3, B
la AT + CH = 6,487.5, B
la AT + CH = 7,487.7, B
la AT + CH =. 8, OFF
el AT + CH =. 9, OFF
el AT + log = ON (Esta entrada es muy importante, se puede ver la situación de las pasarelas de comunicación y la plataforma en la nube, con nodos)
en + el restablecimiento restablece la puerta de entrada, a continuación, iniciar la conexión al servidor.
Estos son los preparativos para el trasplante antes de nodo

texto

inicialización

void LORA_Init (LoRaMainCallback_t *callbacks, LoRaParam_t* LoRaParam )
{
 uint8_t devEui[] = LORAWAN_DEVICE_EUI;
  uint8_t joinEui[] = LORAWAN_JOIN_EUI;    //连接腾讯云平台用不到这个参数
  
  /* init the Tx Duty Cycle*/
  LoRaParamInit = LoRaParam;
  
  /* init the main call backs*/
  LoRaMainCallbacks = callbacks;
  
#if (STATIC_DEVICE_EUI != 1)
  LoRaMainCallbacks->BoardGetUniqueId( devEui );  
#endif
  
#if( OVER_THE_AIR_ACTIVATION != 0 )

  PPRINTF( "OTAA\n\r"); 
  PPRINTF( "DevEui= %02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X\n\r", HEX8(devEui));
  PPRINTF( "AppEui= %02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X\n\r", HEX8(joinEui));
  PPRINTF( "AppKey= %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\n\r", HEX16(AppKey));
#else

#if (STATIC_DEVICE_ADDRESS != 1)
  // Random seed initialization
  srand1( LoRaMainCallbacks->BoardGetRandomSeed( ) );
  // Choose a random device address
  DevAddr = randr( 0, 0x01FFFFFF );
#endif
  PPRINTF( "ABP\n\r"); 
  PPRINTF( "DevEui= %02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X\n\r", HEX8(devEui));
  PPRINTF( "DevAdd=  %08X\n\r", DevAddr) ;
  PPRINTF( "NwkSKey= %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\n\r", HEX16(NwkSEncKey));
  PPRINTF( "AppSKey= %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\n\r", HEX16(AppSKey));
#endif
.
.
.
#elif defined( REGION_CN470 )
  LoRaMacInitialization( &LoRaMacPrimitives, &LoRaMacCallbacks, LORAMAC_REGION_CN470 );
 .
 .
 .
  mibReq.Param.DevEui = devEui;
  mibReq.Param.AppKey = AppKey;
  mibReq.Param.NwkKey = NwkKey; //这几个参数很重要一定要设对,我就  
  mibReq.Param.Class= CLASS_A;  // 因为没设Nwkkey 导致入不网,
  //Lorawan 1.0.x 也要设置,具体原因在下文会详细分析
  .
  .
  .
  LoRaMacStart( );
}

Como puede verse, según algunos de inicialización es la forma en que nuestra red como los ajustes de macro, por lo que el uso de regional inicializado.

red

void LORA_Join( void)
{
    MlmeReq_t mlmeReq;
  
    mlmeReq.Type = MLME_JOIN;
    mlmeReq.Req.Join.Datarate = LoRaParamInit->TxDatarate;
  
    JoinParameters = mlmeReq.Req.Join;

#if( OVER_THE_AIR_ACTIVATION != 0 )
    LoRaMacMlmeRequest( &mlmeReq );    //腾讯云物联网平台要求空中入网的方式,所以定义了这个宏为1,于是调用了这个函数;                                                                       
#else
.
.
.
#endif
}

LoRaMacStatus_t LoRaMacMlmeRequest( MlmeReq_t* mlmeRequest )
{
    LoRaMacStatus_t status = LORAMAC_STATUS_SERVICE_UNKNOWN;
    MlmeConfirmQueue_t queueElement;
    uint8_t macCmdPayload[2] = { 0x00, 0x00 };

    if( mlmeRequest == NULL )
    {
        return LORAMAC_STATUS_PARAMETER_INVALID;
    }
    if( LoRaMacIsBusy( ) == true )
    {
        return LORAMAC_STATUS_BUSY;
    }
    if( LoRaMacConfirmQueueIsFull( ) == true )
    {
        return LORAMAC_STATUS_BUSY;
    }
    .
    .
    .
    switch( mlmeRequest->Type )   //通过入参来判断我们这是是入网请求MLME_JOIN
    {
        case MLME_JOIN:
        {
            if( ( MacCtx.MacState & LORAMAC_TX_DELAYED ) == LORAMAC_TX_DELAYED )
            {
                return LORAMAC_STATUS_BUSY;
            }

            ResetMacParameters( );

            MacCtx.NvmCtx->MacParams.ChannelsDatarate = RegionAlternateDr( MacCtx.NvmCtx->Region, mlmeRequest->Req.Join.Datarate, ALTERNATE_DR );

            queueElement.Status = LORAMAC_EVENT_INFO_STATUS_JOIN_FAIL;

            status = SendReJoinReq( JOIN_REQ );     //我们再进去看这个函数

            if( status != LORAMAC_STATUS_OK )    
            {
					PPRINTF( "joinreq ok\n\r");
                // Revert back the previous datarate ( mainly used for US915 like regions )
                MacCtx.NvmCtx->MacParams.ChannelsDatarate = RegionAlternateDr( MacCtx.NvmCtx->Region, mlmeRequest->Req.Join.Datarate, ALTERNATE_DR_RESTORE );
            }
						else
						{
							PPRINTF( "joinreq not ok\n\r");
						}
            break;
        }
        .
        .
        .
        return status;
}

LoRaMacStatus_t SendReJoinReq( JoinReqIdentifier_t joinReqType )
{
    LoRaMacStatus_t status = LORAMAC_STATUS_OK;
    LoRaMacHeader_t macHdr;
    macHdr.Value = 0;
    bool allowDelayedTx = true;

    // Setup join/rejoin message
    switch( joinReqType )
    {
        case JOIN_REQ:
        {
         .
         .
         .
        }
    }

    // Schedule frame
    status = ScheduleTx( allowDelayedTx );  //再看这个函数
    return status;
}
//谜底快解开了....
static LoRaMacStatus_t ScheduleTx( bool allowDelayedTx )
{
   LoRaMacStatus_t status = LORAMAC_STATUS_PARAMETER_INVALID;
    TimerTime_t dutyCycleTimeOff = 0;
    NextChanParams_t nextChan;
    size_t macCmdsSize = 0;

    // Update back-off
    CalculateBackOff( MacCtx.NvmCtx->LastTxChannel );
    .
    .
    .
     if( MacCtx.NvmCtx->NetworkActivation == ACTIVATION_TYPE_NONE )
    {
        MacCtx.RxWindow1Delay = MacCtx.NvmCtx->MacParams.JoinAcceptDelay1 +   MacCtx.RxWindow1Config.WindowOffset;
        MacCtx.RxWindow2Delay = MacCtx.NvmCtx->MacParams.JoinAcceptDelay2 + MacCtx.RxWindow2Config.WindowOffset;
	    PPRINTF( "MacCtx.RxWindow1Delay is %d\n\r",MacCtx.RxWindow1Delay);
    }
     //这里也重点说一下,很多人入不了网的原因是因为接收窗口的时间不对,从发出入 
    //请求到从网关接收入网应答这个时间间隔是5秒,这个和腾讯云物联网平台的工程师确
    //确认过
 .
 .
 .
     // Secure frame
     //谜底就在这个函数里
    LoRaMacStatus_t retval = SecureFrame( MacCtx.NvmCtx->MacParams.ChannelsDatarate, MacCtx.Channel ); 
    if( retval != LORAMAC_STATUS_OK )
    {
        return retval;
    }

    // Try to send now
    return SendFrameOnChannel( MacCtx.Channel );  
}

== antes de que la red no ha tenido éxito, el contacto profesor Tencent nube Xia Yunfei, volver es MIC mal, MIC maestro de error verano dijo sólo dos razones, en primer lugar, la tecla equivocada, el segundo es el algoritmo mal. ==

Estoy seguro de que el algoritmo no puede estar equivocado, porque no entregaba el código fuente, por lo que volvió a confirmar AppKey y devEui, sí. Después de un período de tiempo de lanzamiento y Tencent dos grandes maestros nube de Dios Xia Yunfei y twowinter (nombre real no sabe ah, ja, ja) orientación y consejos, ver el código de nuevo, la respuesta es la siguiente

static LoRaMacStatus_t SecureFrame( uint8_t txDr, uint8_t txCh )
{
    LoRaMacCryptoStatus_t macCryptoStatus = LORAMAC_CRYPTO_ERROR;
    uint32_t fCntUp = 0;

    switch( MacCtx.TxMsg.Type )
    {
        case LORAMAC_MSG_TYPE_JOIN_REQUEST:  
           //我们来看看下面的函数 LoRaMacCryptoPrepareJoinRequest
            macCryptoStatus = LoRaMacCryptoPrepareJoinRequest( &MacCtx.TxMsg.Message.JoinReq );
            if( LORAMAC_CRYPTO_SUCCESS != macCryptoStatus )
            {
                return LORAMAC_STATUS_CRYPTO_ERROR;
            }
            MacCtx.PktBufferLen = MacCtx.TxMsg.Message.JoinReq.BufSize;
            break;
      .
      .
      .
    return LORAMAC_STATUS_OK;
}

LoRaMacCryptoStatus_t LoRaMacCryptoPrepareJoinRequest( LoRaMacMessageJoinRequest_t* macMsg )     
{
    if( macMsg == 0 )
    {
        return LORAMAC_CRYPTO_ERROR_NPE;
    }
    //这里加密用的是NWK_KEY,  但是我没有设置,所以加密错误,这就是原因,我也打印再次确认过,就是nwk_key。 破案了
    KeyIdentifier_t micComputationKeyID = NWK_KEY;  

    // Add device nonce
#if ( USE_RANDOM_DEV_NONCE == 1 )
    uint32_t devNonce = 0;
    SecureElementRandomNumber( &devNonce );
    CryptoCtx.NvmCtx->DevNonce = devNonce;
#else
    CryptoCtx.NvmCtx->DevNonce++;
#endif
    CryptoCtx.EventCryptoNvmCtxChanged( );
    macMsg->DevNonce = CryptoCtx.NvmCtx->DevNonce;

#if( USE_LRWAN_1_1_X_CRYPTO == 1 )   //这里是USE_LRWAN_1_1_X 的宏,但是我的是1_0_X, 所以为零
    // Derive lifetime session keys
    if( DeriveLifeTimeSessionKey( J_S_INT_KEY, macMsg->DevEUI ) != LORAMAC_CRYPTO_SUCCESS )
    {
        return LORAMAC_CRYPTO_ERROR;
    }
    if( DeriveLifeTimeSessionKey( J_S_ENC_KEY, macMsg->DevEUI ) != LORAMAC_CRYPTO_SUCCESS )
    {
        return LORAMAC_CRYPTO_ERROR;
    }
#endif

    // Serialize message
    if( LoRaMacSerializerJoinRequest( macMsg ) != LORAMAC_SERIALIZER_SUCCESS )
    {
        return LORAMAC_CRYPTO_ERROR_SERIALIZER;
    }

    // Compute mic   这里计算用到了上面的nwk_key,破案了
    if( SecureElementComputeAesCmac( NULL, macMsg->Buffer, ( LORAMAC_JOIN_REQ_MSG_SIZE - LORAMAC_MIC_FIELD_SIZE ), micComputationKeyID, &macMsg->MIC ) != SECURE_ELEMENT_SUCCESS )
    {
        return LORAMAC_CRYPTO_ERROR_SECURE_ELEMENT_FUNC;
    }

    // Reserialize message to add the MIC
    if( LoRaMacSerializerJoinRequest( macMsg ) != LORAMAC_SERIALIZER_SUCCESS )
    {
        return LORAMAC_CRYPTO_ERROR_SERIALIZER;
    }

    return LORAMAC_CRYPTO_SUCCESS;
}

Transmisión y recepción

Enviar y recibir por lo que no encontrará dificultades, envía una función de llamada directa en la línea, ya que es un dispositivo de clase A será después del envío, recepción recibe ventana abierta, sino que registró una función de envío

bool LORA_send(lora_AppData_t* AppData, LoraConfirm_t IsTxConfirmed)
{
    McpsReq_t mcpsReq;
    LoRaMacTxInfo_t txInfo;
  
    /*if certification test are on going, application data is not sent*/
    if (certif_running() == true)
    {
			PPRINTF("certif_run\r\n");
      return false;
    }
    
    if( LoRaMacQueryTxPossible( AppData->BuffSize, &txInfo ) != LORAMAC_STATUS_OK )
    {
        // Send empty frame in order to flush MAC commands
        mcpsReq.Type = MCPS_UNCONFIRMED;
        mcpsReq.Req.Unconfirmed.fBuffer = NULL;
        mcpsReq.Req.Unconfirmed.fBufferSize = 0;
        mcpsReq.Req.Unconfirmed.Datarate = LoRaParamInit->TxDatarate;
    }
    else
    {
        if( IsTxConfirmed == LORAWAN_UNCONFIRMED_MSG )
        {
            mcpsReq.Type = MCPS_UNCONFIRMED;
            mcpsReq.Req.Unconfirmed.fPort = AppData->Port;
            mcpsReq.Req.Unconfirmed.fBufferSize = AppData->BuffSize;
            mcpsReq.Req.Unconfirmed.fBuffer = AppData->Buff;
            mcpsReq.Req.Unconfirmed.Datarate = LoRaParamInit->TxDatarate;
        }
        else
        {
            mcpsReq.Type = MCPS_CONFIRMED;
            mcpsReq.Req.Confirmed.fPort = AppData->Port;
            mcpsReq.Req.Confirmed.fBufferSize = AppData->BuffSize;
            mcpsReq.Req.Confirmed.fBuffer = AppData->Buff;
            mcpsReq.Req.Confirmed.NbTrials = 8;
            mcpsReq.Req.Confirmed.Datarate = LoRaParamInit->TxDatarate;
        }
    }
    if( LoRaMacMcpsRequest( &mcpsReq ) == LORAMAC_STATUS_OK )
    {
        return false;
    }
    return true;
}

Todavía publicó un mapa
Aquí Insertar imagen Descripción
de todo el contenido está por encima.
Por último, gracias maestros Tencent nube Xia Yunfei y twowinter de nuevo.
Si está interesado en Lora puede mirar twowinter artículos, puede ser muy útil en el siguiente enlace
Enlace
http://blog.csdn.net/iotisan/

Link de descarga

Publicó un artículo original · ganado elogios 0 · Vistas 150

Supongo que te gusta

Origin blog.csdn.net/lintonxie/article/details/105038547
Recomendado
Clasificación