/* / _____) _ | | ( (____ _____ ____ _| |_ _____ ____| |__ \____ \| ___ | (_ _) ___ |/ ___) _ \ _____) ) ____| | | || |_| ____( (___| | | | (______/|_____)_|_|_| \__)_____)\____)_| |_| (C)2013 Semtech ___ _____ _ ___ _ _____ ___ ___ ___ ___ / __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __| \__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _| |___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___| embedded.connectivity.solutions=============== Description: LoRa MAC layer implementation License: Revised BSD License, see LICENSE.TXT file include in the project Maintainer: Miguel Luis ( Semtech ), Gregory Cristian ( Semtech ) and Daniel Jäckle ( STACKFORCE ) */ #include "bsp.h" //#include "stdint.h" #include #include "LoRaMacCrypto.h" #include "LoRaMac.h" #include "utilities.h" #include "usart.h" /*! * Maximum PHY layer payload size */ #define LORAMAC_PHY_MAXPAYLOAD 255 /*! * Maximum MAC commands buffer size */ #define LORA_MAC_COMMAND_MAX_LENGTH 15 /*! * Device IEEE EUI */ // 0x80 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 static uint8_t LoRaMacDevEui[] = { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }; /*! * Application IEEE EUI */ // 0x8a 7c 07 e4 f7 24 6e 25 6c fb 37 50 fc 92 ec d6 static uint8_t LoRaMacAppEui[] = { 0x8a, 0x7c, 0x07, 0xe4, 0xf7, 0x24, 0x6e, 0x25 }; /*! * AES encryption/decryption cipher application key */ //0xabaab826f4797818854bdbdbaa55029c static uint8_t LoRaMacAppKey[] = { 0xab, 0xaa, 0xb8, 0x26, 0xf4, 0x79, 0x78, 0x18, 0x85, 0x4b, 0xdb, 0xdb, 0xaa, 0x55, 0x02, 0x9c }; /*! * AES encryption/decryption cipher network session key */ static uint8_t LoRaMacNwkSKey[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; /*! * AES encryption/decryption cipher application session key */ static uint8_t LoRaMacAppSKey[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; /*! * Device nonce is a random value extracted by issuing a sequence of RSSI * measurements */ static uint16_t LoRaMacDevNonce; /*! * Network ID ( 3 bytes ) */ static uint32_t LoRaMacNetID; /*! * Mote Address */ static uint32_t LoRaMacDevAddr; /*! * Indicates if the node supports repeaters */ static bool RepeaterSupport; /*! * Buffer containing the data to be sent or received. */ static uint8_t LoRaMacBuffer[LORAMAC_PHY_MAXPAYLOAD]; /*! * Length of packet in LoRaMacBuffer */ static uint16_t LoRaMacBufferPktLen = 0; /*! * Buffer containing the upper layer data. */ static uint8_t LoRaMacPayload[LORAMAC_PHY_MAXPAYLOAD]; static uint8_t LoRaMacRxPayload[LORAMAC_PHY_MAXPAYLOAD]; /*! * LoRaMAC frame counter. Each time a packet is sent the counter is incremented. * Only the 16 LSB bits are sent */ static uint32_t UpLinkCounter = 1; /*! * LoRaMAC frame counter. Each time a packet is received the counter is incremented. * Only the 16 LSB bits are received */ static uint32_t DownLinkCounter = 0; /*! * Indicates if the MAC layer has already joined a network. */ static bool IsLoRaMacNetworkJoined = false; /*! * LoRaMac ADR control status */ static bool AdrCtrlOn = false; /*! * Counts the number of missed ADR acknowledgements */ static uint32_t AdrAckCounter = 0; /*! * If the node has sent a FRAME_TYPE_DATA_CONFIRMED_UP this variable indicates * if the nodes needs to manage the server acknowledgement. */ static bool NodeAckRequested = false; /*! * If the server has sent a FRAME_TYPE_DATA_CONFIRMED_DOWN this variable indicates * if the ACK bit must be set for the next transmission */ static bool SrvAckRequested = false; /* extern uint8_t PrepareJoinRequestFrame(uint8_t *macHdr, MACPayload_t *mPayload_t,void *fBuffer, uint16_t fBufferSize) { if(*macHdr == 0x1c) //0x1c :Mtype=000b,RFU=111b,Major=00b { fBuffer[0]=*macHdr; fBuffer[1]=(mPayload_t->AppEUI >> 56) & 0xff; fBuffer[2]=(mPayload_t->AppEUI >> 48) & 0xff; fBuffer[3]=(mPayload_t->AppEUI >> 40) & 0xff; fBuffer[4]=(mPayload_t->AppEUI >> 32) & 0xff; fBuffer[5]=(mPayload_t->AppEUI >> 24) & 0xff; fBuffer[6]=(mPayload_t->AppEUI >> 16) & 0xff; fBuffer[7]=(mPayload_t->AppEUI ) & 0xff; } else return ERROR; } */ uint8_t fDangCiDataSample[]={ 0xbb, //前导码 0x1b, //长度码 0xff, //帧号 0x86, //命令码 0x00, //gun_num,00H:1号枪,01H:2号枪 0x00, //status,00H:正常抄报税;01H:重复抄报税。 '2','2', //22日 '1','5', //15点 '0','9', //09分 '1','2','3','.','0','0', //油量123.45L(或公斤) '6','2','9','.','6','0', //金额629.56(元) '5','.','1','0', //单价 0x65 //校验码 }; uint8_t fZongLeiJiDataSample[]={ 0xbb, //前导码 0x21, //长度码 0xff, //帧号 0x89, //命令码 0x00, //gun_num,00H:1号枪,01H:2号枪 0x00, //mode,00H:正常抄报税;01H:重复抄报税。 '1','2','3','4','5','6','7','8','9','.','1','2',//油量123.45L(或公斤) '6','1','7','2','8','3','9','4','5','.','6','0',//油量629.56(元) '5','.','1','0', //单价 0x0c //校验码 }; uint8_t jDangCiDataSample[]={ 0xbb, //前导码 0x1b, //长度码 0x81, //帧号 0x00, //端口号 0xa1, //命令码 0x11, //累计类型 0x00, //gun_num,00H:1号枪,01H:2号枪 0x12, //12日 0x18, //18时 0x35, //35分 0x00,0x12,0x34,0x56,0x78, //油量123456.78L(或公斤) 0x00,0x62,0x96,0x29,0x58, //金额629629.578(元) 0x00,0x00,0x00,0x05,0x10, //单价5.1 0x65,0x00 //校验码 }; uint8_t jZongLeiJiDataSample[]={ 0xbb, //前导码 0x1b, //长度码 0x81, //帧号 0x00, //端口号 0xa1, //命令码 0x14, //累计类型 0x00, //gun_num,00H:1号枪,01H:2号枪 0x00,0x00,0x00,0x12,0x34,0x56,0x78, //油量123456.78L(或公斤) 0x00,0x00,0x00,0x62,0x96,0x29,0x58, //金额629629.578(元) 0x0c,0x00 //校验码 }; uint8_t BinToByte(uint8_t Value) { uint8_t tmp = Value & 0x0f; if(tmp<0x0a) return tmp+'0'; else return tmp - 0x0a + 'A'; } uint8_t USART1_SendNASCII(uint8_t *p,uint16_t size) { uint8_t tmp; uint16_t i=0; for(i=0;i>4 ) & 0x0f; if(tmp<0x0a) USART1_SendByte( tmp+'0'); else USART1_SendByte( tmp - 0x0a + 'A'); tmp = (*(p+i) >>0 ) & 0x0f; if(tmp<0x0a) USART1_SendByte( tmp+'0'); else USART1_SendByte( tmp - 0x0a + 'A'); } return 0; } LoRaMacStatus_t PrepareFrame( LoRaMacHeader_t *macHdr, LoRaMacFrameCtrl_t *fCtrl, uint8_t fPort, void *fBuffer, uint16_t fBufferSize ) { //uint16_t i; uint8_t pktHeaderLen = 0; uint32_t mic = 0; const void* payload = fBuffer; uint8_t payloadSize = fBufferSize; uint8_t framePort = fPort; LoRaMacBufferPktLen = 0; NodeAckRequested = false; if( fBuffer == NULL ) { fBufferSize = 0; } LoRaMacBuffer[pktHeaderLen++] = macHdr->Value; switch( macHdr->Bits.MType ) { case FRAME_TYPE_JOIN_REQ: LoRaMacBufferPktLen = pktHeaderLen; memcpyr( LoRaMacBuffer + LoRaMacBufferPktLen, LoRaMacAppEui, 8 ); LoRaMacBufferPktLen += 8; memcpyr( LoRaMacBuffer + LoRaMacBufferPktLen, LoRaMacDevEui, 8 ); LoRaMacBufferPktLen += 8; LoRaMacDevNonce = 0xf85e;//Radio.Random( ); LoRaMacBuffer[LoRaMacBufferPktLen++] = LoRaMacDevNonce & 0xFF; LoRaMacBuffer[LoRaMacBufferPktLen++] = ( LoRaMacDevNonce >> 8 ) & 0xFF; LoRaMacJoinComputeMic( LoRaMacBuffer, LoRaMacBufferPktLen & 0xFF, LoRaMacAppKey, &mic ); LoRaMacBuffer[LoRaMacBufferPktLen++] = mic & 0xFF; LoRaMacBuffer[LoRaMacBufferPktLen++] = ( mic >> 8 ) & 0xFF; LoRaMacBuffer[LoRaMacBufferPktLen++] = ( mic >> 16 ) & 0xFF; LoRaMacBuffer[LoRaMacBufferPktLen++] = ( mic >> 24 ) & 0xFF; break; case FRAME_TYPE_DATA_UNCONFIRMED_UP: if( IsLoRaMacNetworkJoined == false ) { //return LORAMAC_STATUS_NO_NETWORK_JOINED; // No network has been joined yet } fCtrl->Bits.AdrAckReq = false;//AdrNextDr( fCtrl->Bits.Adr, true, &ChannelsDatarate ); if( (fBufferSize+14) > 127 ) { return LORAMAC_STATUS_LENGTH_ERROR; } if( SrvAckRequested == true ) { SrvAckRequested = false; fCtrl->Bits.Ack = 1; } LoRaMacBuffer[pktHeaderLen++] = ( LoRaMacDevAddr ) & 0xFF; LoRaMacBuffer[pktHeaderLen++] = ( LoRaMacDevAddr >> 8 ) & 0xFF; LoRaMacBuffer[pktHeaderLen++] = ( LoRaMacDevAddr >> 16 ) & 0xFF; LoRaMacBuffer[pktHeaderLen++] = ( LoRaMacDevAddr >> 24 ) & 0xFF; fCtrl->Bits.FOptsLen=1; //自定义协议,长度值始终为1 LoRaMacBuffer[pktHeaderLen++] = fCtrl->Value; LoRaMacBuffer[pktHeaderLen++] = UpLinkCounter & 0xFF; LoRaMacBuffer[pktHeaderLen++] = ( UpLinkCounter >> 8 ) & 0xFF; LoRaMacBuffer[pktHeaderLen++] = 0x01; //自定义协议,当 PHYPayload.MACPayload.Fport==1~223 时, PHYPayload.MACPayload.FHDR.Fopts=0x01 LoRaMacBuffer[pktHeaderLen++] = framePort; //自定义端口号,参考《自定义协议》LoRaWAN_PayLoadVersion部分 if( ( payload != NULL ) && ( payloadSize > 0 ) ) { printf("\r\n"); printf("payload=\r\n"); USART_printfHex((uint8_t* ) payload,payloadSize); //printf("\r\n"); LoRaMacPayloadEncrypt( (uint8_t* ) payload, payloadSize, LoRaMacAppSKey, LoRaMacDevAddr, UP_LINK, UpLinkCounter, LoRaMacPayload ); memcpy1( LoRaMacBuffer + pktHeaderLen, LoRaMacPayload, payloadSize ); printf("LoRaMacPayloadEncrypt=\r\n"); USART_printfHex(LoRaMacPayload,payloadSize); //printf("\r\n"); LoRaMacPayloadDecrypt( LoRaMacPayload, payloadSize, LoRaMacAppSKey, LoRaMacDevAddr, UP_LINK, UpLinkCounter, (uint8_t* ) payload ); printf("LoRaMacPayloadDecrypt=\r\n"); USART_printfHex((uint8_t* ) payload,payloadSize); //printf("\r\n"); } LoRaMacBufferPktLen = pktHeaderLen + payloadSize; LoRaMacComputeMic( LoRaMacBuffer, LoRaMacBufferPktLen, LoRaMacNwkSKey, LoRaMacDevAddr, UP_LINK, UpLinkCounter, &mic ); LoRaMacBuffer[LoRaMacBufferPktLen + 0] = mic & 0xFF; LoRaMacBuffer[LoRaMacBufferPktLen + 1] = ( mic >> 8 ) & 0xFF; LoRaMacBuffer[LoRaMacBufferPktLen + 2] = ( mic >> 16 ) & 0xFF; LoRaMacBuffer[LoRaMacBufferPktLen + 3] = ( mic >> 24 ) & 0xFF; LoRaMacBufferPktLen += LORAMAC_MFR_LEN; break; case FRAME_TYPE_PROPRIETARY: if( ( fBuffer != NULL ) && ( fBufferSize > 0 ) ) { memcpy1( LoRaMacBuffer + pktHeaderLen, ( uint8_t* ) fBuffer, fBufferSize ); LoRaMacBufferPktLen = pktHeaderLen + fBufferSize; } break; default: return LORAMAC_STATUS_SERVICE_UNKNOWN; } return LORAMAC_STATUS_OK; } void sendJoinRequest(void) { LoRaMacHeader_t macHdr; uint32_t i=0; macHdr.Value=0x1c;// if( PrepareFrame( &macHdr, NULL, 0, NULL, 0)==LORAMAC_STATUS_OK) { printf("\r\n"); USART_printfHex(LoRaMacBuffer,LoRaMacBufferPktLen); } } void sendUnconfirmUp(void) { LoRaMacHeader_t macHdr; LoRaMacFrameCtrl_t fCtrl; uint8_t fPort; uint32_t i=0; LoRaMacDevAddr = 0x83000031; fCtrl.Value=0x01; macHdr.Value=0x5c;// fPort=0x10; if( PrepareFrame( &macHdr, &fCtrl, fPort, fDangCiDataSample, sizeof(fDangCiDataSample))==LORAMAC_STATUS_OK) { USART_printfHex(LoRaMacBuffer,LoRaMacBufferPktLen); } if( PrepareFrame( &macHdr, &fCtrl, fPort, fZongLeiJiDataSample, sizeof(fZongLeiJiDataSample))==LORAMAC_STATUS_OK) { USART_printfHex(LoRaMacBuffer,LoRaMacBufferPktLen); } if( PrepareFrame( &macHdr, &fCtrl, fPort, jDangCiDataSample, sizeof(jDangCiDataSample))==LORAMAC_STATUS_OK) { USART_printfHex(LoRaMacBuffer,LoRaMacBufferPktLen); } if( PrepareFrame( &macHdr, &fCtrl, fPort, jZongLeiJiDataSample, sizeof(jZongLeiJiDataSample))==LORAMAC_STATUS_OK) { USART_printfHex(LoRaMacBuffer,LoRaMacBufferPktLen); } }