Sending messages through LoRaWAN using STM32

1.9k views Asked by At

How do I send the messages through LoRaWAN?

static void PrepareTxFrame( uint8_t port )
{
switch( port ) {
    case 10: {
        int pos = 0;

        pc.printf("Prepare message\n");
#if 0
        uint32_t tempValue = ( uint32_t )( LightValue * 1000000.0 );
        AppData[0] = LightMode;
        AppData[1] = ( ( tempValue & 0xFF000000 ) >> 24 ) & 0xFF;
        AppData[2] = ( ( tempValue & 0x00FF0000 ) >> 16 ) & 0xFF;
        AppData[3] = ( ( tempValue & 0x0000FF00 ) >> 8 ) & 0xFF;
        AppData[4] = ( tempValue & 0x000000FF );
#else
        AppData[pos] = count;

        pc.printf("\n\r");
        pc.printf("The value of the counter is : %d", count);
        count++;
        pc.printf("\n\r");

        time_t seconds = time(NULL);
        printf("The time is %s", ctime(&seconds));
        AppData[++pos] = seconds;


        pc.printf("%d \n %d", AppData[0], AppData[1]);
        pc.printf("\n\r");
#endif
        pc.printf("Message Ready\n");
    }
    break;
    case 15: {
        int pos = 0;
        AppData[pos++] = AppLedStateOn;
#if 0

        if( IsTxConfirmed == true )
        {
            AppData[pos++] = LoRaMacDownlinkStatus.DownlinkCounter >> 8;
            AppData[pos++] = LoRaMacDownlinkStatus.DownlinkCounter;
            AppData[pos++] = LoRaMacDownlinkStatus.Rssi >> 8;
            AppData[pos++] = LoRaMacDownlinkStatus.Rssi;
            AppData[pos++] = LoRaMacDownlinkStatus.Snr;
        }
#endif
        AppDataSize = pos;
    }
    break;
    case 224:
        if( ComplianceTest.LinkCheck == true ) {
            ComplianceTest.LinkCheck = false;
            AppDataSize = 3;
            AppData[0] = 5;
            AppData[1] = ComplianceTest.DemodMargin;
            AppData[2] = ComplianceTest.NbGateways;
            ComplianceTest.State = 1;
        } else {
            switch( ComplianceTest.State ) {
                case 4:
                    ComplianceTest.State = 1;
                    break;
                case 1:
                    AppDataSize = 2;
                    AppData[0] = ComplianceTest.DownLinkCounter >> 8;
                    AppData[1] = ComplianceTest.DownLinkCounter;
                    break;
            }
        }
        break;
    default:
        break;
  }
 }

/*!
 * \brief
 *
  * Prepares the pay-load of the frame
  *
 * \retval  [0: frame could be send, 1: error]
 */
static bool SendFrame( void )
{
 McpsReq_t mcpsReq;
 LoRaMacTxInfo_t txInfo;

if( LoRaMacQueryTxPossible( AppDataSize, &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 = LORAWAN_DEFAULT_DATARATE;

    LoRaMacUplinkStatus.Acked = false;
    LoRaMacUplinkStatus.Port = 0;
    LoRaMacUplinkStatus.Buffer = NULL;
    LoRaMacUplinkStatus.BufferSize = 0;
    SerialDisplayUpdateFrameType( false );
} else {
    LoRaMacUplinkStatus.Acked = false;
    LoRaMacUplinkStatus.Port = AppPort;
    LoRaMacUplinkStatus.Buffer = AppData;
    LoRaMacUplinkStatus.BufferSize = AppDataSize;
    SerialDisplayUpdateFrameType( IsTxConfirmed );

    if( IsTxConfirmed == false ) {
        mcpsReq.Type = MCPS_UNCONFIRMED;
        mcpsReq.Req.Unconfirmed.fPort = AppPort;
        mcpsReq.Req.Unconfirmed.fBuffer = AppData;
        mcpsReq.Req.Unconfirmed.fBufferSize = AppDataSize;
        mcpsReq.Req.Unconfirmed.Datarate = LORAWAN_DEFAULT_DATARATE;
    } else {
        mcpsReq.Type = MCPS_CONFIRMED;
        mcpsReq.Req.Confirmed.fPort = AppPort;
        mcpsReq.Req.Confirmed.fBuffer = AppData;
        mcpsReq.Req.Confirmed.fBufferSize = AppDataSize;
        mcpsReq.Req.Confirmed.NbTrials = 8;
        mcpsReq.Req.Confirmed.Datarate = LORAWAN_DEFAULT_DATARATE;
    }
}

if( LoRaMacMcpsRequest( &mcpsReq ) == LORAMAC_STATUS_OK ) {
    return false;
}
return true;
}

Will the counter data and the time be sent? Also is the data in AppData the ones to be transmitted? I want the count and the timestamp to be sent every time the LoRa device transmits.

1

There are 1 answers

3
Hugo Bevilacqua On BEST ANSWER

The payload to send (AppData) is given to the LoRaMAC layer through the MCPS (MAC Common Part Sublayer) request, e.g. for an unconfirmed frame:

mcpsReq.Req.Unconfirmed.fBuffer = AppData;

So physically (i.e. by RF), AppData is sent but it's encrypted and encapsulated before.

PrepareFrame() function builds the frame to send according to the PHYPayload scheme (See the "MAC Message Formats" part in the LoRaWAN™ Specification 1.0.2 document), following these fields:

  • MHDR (1 byte) Mac header
  • DevAddr (4 bytes) Address of the end-device
  • FCtrl (1 byte) Frame control
  • FCnt (2 bytes) Frame counter
  • FOpts (0 - 15 bytes) Frame options
  • FPort (0 - 1 byte) Port field
  • FRMPayload (0 - N bytes) MAC Frame Payload Encryption, your AppData encrypted
  • MIC (4 bytes) Message Integrity Code


FRMPayload is encrypted according to FPort. The encryption algorithm is based on AES 128.
If FPort = [1..255], the AppSKey key will be used to encrypt your payload.
Else (FPort = 0), it's encrypted by using the NwkSKey key.
See the LoRaMacPayloadEncrypt() function for more details.

PHYPayload will be encapsulated by the Radio PHY Layer and sent through RF.