application layer with: button, LED, pot, tempSense
Fork of LoRaWAN-demo-72-bootcamp by
Use with sx1272 shield with grove peripherals connected:
D8 D9: Button | RX TX | A3 A4: TempSense |
D6 D7: | SCL SDA : LED | A1 A2: Pot |
Button
Sends to different payloads: short press (under 1 sec)
long press: held down > 1 sec.
serial console keys
115200bps, 8N1
Enter key not used
Keys '0' to '3': cayenne channel number
'0': pot (rotary sensor)
'1': temperature
'
2': digital out
'3': analog out
Diff: app/main.cpp
- Revision:
- 11:018e7e28161d
- Parent:
- 10:52810ecbd83b
- Child:
- 12:662ff73ce484
diff -r 52810ecbd83b -r 018e7e28161d app/main.cpp --- a/app/main.cpp Tue Jan 30 22:49:12 2018 +0000 +++ b/app/main.cpp Sat Feb 03 00:44:16 2018 +0000 @@ -115,7 +115,7 @@ /*! * User application data size */ -static uint8_t AppDataSize = LORAWAN_APP_DATA_SIZE; +static uint8_t gAppDataSize = LORAWAN_APP_DATA_SIZE; /*! * User application data buffer size @@ -130,7 +130,7 @@ /*! * Indicates if the node is sending confirmed or unconfirmed messages */ -static uint8_t IsTxConfirmed = LORAWAN_CONFIRMED_MSG_ON; +static uint8_t gIsTxConfirmed = LORAWAN_CONFIRMED_MSG_ON; /*! * Device states @@ -222,13 +222,101 @@ //SerialDisplayUpdateLedState( 3, AppLedStateOn ); } + +void LoRaMacStatus_toString(LoRaMacStatus_t s, char* out) +{ + switch (s) { + case LORAMAC_STATUS_PARAMETER_INVALID: + strcpy(out, "PARAMTER_INVALID"); + break; + case LORAMAC_STATUS_BUSY: + strcpy(out, "BUSY"); + break; + default: + sprintf(out, "<%u>", s); + break; + } +} + +volatile unsigned sendCnt = 0; +/*! + * \brief Prepares the payload of the frame + * + * \retval [0: frame could be send, 1: error] + */ +static bool SendFrame( uint8_t len, bool conf ) +{ + char str[48]; + LoRaMacStatus_t status; + McpsReq_t mcpsReq; + LoRaMacTxInfo_t txInfo; + + if( LoRaMacQueryTxPossible( len, &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 = len;//AppDataSize; + SerialDisplayUpdateFrameType( conf/*IsTxConfirmed*/ ); + + if( conf == false ) { + mcpsReq.Type = MCPS_UNCONFIRMED; + mcpsReq.Req.Unconfirmed.fPort = AppPort; + mcpsReq.Req.Unconfirmed.fBuffer = AppData; + mcpsReq.Req.Unconfirmed.fBufferSize = len; + 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 = len; + mcpsReq.Req.Confirmed.NbTrials = 8; + mcpsReq.Req.Confirmed.Datarate = LORAWAN_DEFAULT_DATARATE; + } + } + + sendCnt++; + status = LoRaMacMcpsRequest( &mcpsReq ); + if (status == LORAMAC_STATUS_OK) { + vt.SetCursorPos( 44, 1 ); + vt.printf("%u sendFrame() OK\e[K", sendCnt); + SerialDisplayUpdateUplink( + LoRaMacUplinkStatus.Acked, + LoRaMacUplinkStatus.Datarate, + LoRaMacUplinkStatus.UplinkCounter, + LoRaMacUplinkStatus.Port, + LoRaMacUplinkStatus.Buffer, + LoRaMacUplinkStatus.BufferSize + ); + return false; + } + LoRaMacStatus_toString(status, str); + vt.SetCursorPos( 44, 1 ); + vt.printf("%u sendFrame() %s\e[K", sendCnt, str); + return true; +} + uint8_t c_ch; void SerialRxProcess( void ) { + LoRaMacStatus_t status; + MlmeReq_t mlmeReq; + if( SerialDisplayReadable( ) == true ) { char ch = SerialDisplayGetChar(); - if ( ch >= '0' || ch <= '9') { + if ( ch >= '0' && ch <= '9') { c_ch = ch - '0'; DeviceState = DEVICE_STATE_SEND; return; @@ -239,6 +327,12 @@ // Refresh Serial screen SerialDisplayRefresh( ); break; + case 'L': + mlmeReq.Type = MLME_LINK_CHECK; + status = LoRaMacMlmeRequest( &mlmeReq ); + if (status == LORAMAC_STATUS_OK) + SendFrame(0, false); + break; default: break; } @@ -285,6 +379,7 @@ const unsigned R0 = 100000; const unsigned B = 4275; + volatile TimerTime_t buttonStartAt; DigitalIn d8(D8); DigitalOut extLed(D15); @@ -299,50 +394,50 @@ float t, f, R; if (c_ch != 0xff) { - AppDataSize = 0; - AppData[AppDataSize++] = c_ch; + gAppDataSize = 0; + AppData[gAppDataSize++] = c_ch; switch (c_ch) { case CAYENNE_CH_TEMP: - AppData[AppDataSize++] = LPP_TEMPERATURE; - u16 = a3.read_u16(); - R = 65535 / u16 - 1.0; + AppData[gAppDataSize++] = LPP_TEMPERATURE; + u16 = a3.read_u16() >> 4; + R = 4096.0 / u16 - 1.0; R = R0 * R; t = 1.0/(log(R/R0)/B+1/298.15)-273.15; u16 = t * 10; // 0.1C per bit - AppData[AppDataSize++] = u16 >> 8; - AppData[AppDataSize++] = u16; + AppData[gAppDataSize++] = u16 >> 8; + AppData[gAppDataSize++] = u16; break; case CAYENNE_CH_POT: - AppData[AppDataSize++] = LPP_ANALOG_INPUT; + AppData[gAppDataSize++] = LPP_ANALOG_INPUT; u16 = a1.read_u16(); // pot (rotary angle) f = u16 / 198.6; // scale 65535/3.3 to 0.01v per bit rot = (uint16_t) f; - AppData[AppDataSize++] = rot >> 8; - AppData[AppDataSize++] = rot; + AppData[gAppDataSize++] = rot >> 8; + AppData[gAppDataSize++] = rot; break; case CAYENNE_CH_DOUT: - AppData[AppDataSize++] = LPP_DIGITAL_OUTPUT; - AppData[AppDataSize++] = extLed.read(); + AppData[gAppDataSize++] = LPP_DIGITAL_OUTPUT; + AppData[gAppDataSize++] = extLed.read(); break; case CAYENNE_CH_AOUT: - AppData[AppDataSize++] = LPP_ANALOG_OUTPUT; + AppData[gAppDataSize++] = LPP_ANALOG_OUTPUT; u16 = pwm.read() * 100; - AppData[AppDataSize++] = u16 >> 8; - AppData[AppDataSize++] = u16; + AppData[gAppDataSize++] = u16 >> 8; + AppData[gAppDataSize++] = u16; break; } return; } else if (cayenne_ack_ch != -1) { switch (cayenne_ack_ch) { case CAYENNE_CH_DOUT: - AppData[AppDataSize++] = LPP_DIGITAL_OUTPUT; - AppData[AppDataSize++] = extLed.read(); + AppData[gAppDataSize++] = LPP_DIGITAL_OUTPUT; + AppData[gAppDataSize++] = extLed.read(); break; case CAYENNE_CH_AOUT: - AppData[AppDataSize++] = LPP_ANALOG_OUTPUT; + AppData[gAppDataSize++] = LPP_ANALOG_OUTPUT; u16 = pwm.read() * 100; - AppData[AppDataSize++] = u16 >> 8; - AppData[AppDataSize++] = u16; + AppData[gAppDataSize++] = u16 >> 8; + AppData[gAppDataSize++] = u16; break; } cayenne_ack_ch = -1; @@ -352,10 +447,10 @@ TimerTime_t duration = TimerGetCurrentTime() - buttonStartAt; vt.SetCursorPos( 41, 1 ); if (duration > 1000) { - AppDataSize = 0; - AppData[AppDataSize++] = CAYENNE_CH_DOUT; - AppData[AppDataSize++] = LPP_DIGITAL_OUTPUT; - AppData[AppDataSize++] = extLed.read(); + gAppDataSize = 0; + AppData[gAppDataSize++] = CAYENNE_CH_DOUT; + AppData[gAppDataSize++] = LPP_DIGITAL_OUTPUT; + AppData[gAppDataSize++] = extLed.read(); vt.printf("send outputs ", duration); return; } else @@ -364,34 +459,34 @@ switch( port ) { case LORAWAN_APP_PORT: - AppDataSize = 0; - AppData[AppDataSize++] = CAYENNE_CH_TEMP; - AppData[AppDataSize++] = LPP_TEMPERATURE; - u16 = a3.read_u16(); - R = 65535 / u16 - 1.0; + gAppDataSize = 0; + AppData[gAppDataSize++] = CAYENNE_CH_TEMP; + AppData[gAppDataSize++] = LPP_TEMPERATURE; + u16 = a3.read_u16() >> 4; + R = 4096.0 / u16 - 1.0; R = R0 * R; t = 1.0/(log(R/R0)/B+1/298.15)-273.15; u16 = t * 10; // 0.1C per bit - AppData[AppDataSize++] = u16 >> 8; - AppData[AppDataSize++] = u16; - AppData[AppDataSize++] = CAYENNE_CH_POT; - AppData[AppDataSize++] = LPP_ANALOG_INPUT; + AppData[gAppDataSize++] = u16 >> 8; + AppData[gAppDataSize++] = u16; + AppData[gAppDataSize++] = CAYENNE_CH_POT; + AppData[gAppDataSize++] = LPP_ANALOG_INPUT; u16 = a1.read_u16(); // pot (rotary angle) f = u16 / 198.6; // scale 65535/3.3 to 0.01v per bit rot = (uint16_t) f; - AppData[AppDataSize++] = rot >> 8; - AppData[AppDataSize++] = rot; + AppData[gAppDataSize++] = rot >> 8; + AppData[gAppDataSize++] = rot; - AppData[AppDataSize++] = CAYENNE_CH_DOUT; - AppData[AppDataSize++] = LPP_DIGITAL_OUTPUT; - AppData[AppDataSize++] = extLed.read(); + AppData[gAppDataSize++] = CAYENNE_CH_DOUT; + AppData[gAppDataSize++] = LPP_DIGITAL_OUTPUT; + AppData[gAppDataSize++] = extLed.read(); vt.SetCursorPos( 41, 1 ); vt.printf("u16:%u, f:%f, rot:%u t:%.1f\e[K", u16, f, rot, t); break; case 224: if( ComplianceTest.LinkCheck == true ) { ComplianceTest.LinkCheck = false; - AppDataSize = 3; + gAppDataSize = 3; AppData[0] = 5; AppData[1] = ComplianceTest.DemodMargin; AppData[2] = ComplianceTest.NbGateways; @@ -402,7 +497,7 @@ ComplianceTest.State = 1; break; case 1: - AppDataSize = 2; + gAppDataSize = 2; AppData[0] = ComplianceTest.DownLinkCounter >> 8; AppData[1] = ComplianceTest.DownLinkCounter; break; @@ -414,89 +509,6 @@ } } -void LoRaMacStatus_toString(LoRaMacStatus_t s, char* out) -{ - switch (s) { - case LORAMAC_STATUS_PARAMETER_INVALID: - strcpy(out, "PARAMTER_INVALID"); - break; - case LORAMAC_STATUS_BUSY: - strcpy(out, "BUSY"); - break; - default: - sprintf(out, "<%u>", s); - break; - } -} - -volatile unsigned sendCnt = 0; -/*! - * \brief Prepares the payload of the frame - * - * \retval [0: frame could be send, 1: error] - */ -static bool SendFrame( void ) -{ - char str[48]; - LoRaMacStatus_t status; - 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; - } - } - - sendCnt++; - status = LoRaMacMcpsRequest( &mcpsReq ); - if (status == LORAMAC_STATUS_OK) { - vt.SetCursorPos( 44, 1 ); - vt.printf("%u sendFrame() OK\e[K", sendCnt); - SerialDisplayUpdateUplink( - LoRaMacUplinkStatus.Acked, - LoRaMacUplinkStatus.Datarate, - LoRaMacUplinkStatus.UplinkCounter, - LoRaMacUplinkStatus.Port, - LoRaMacUplinkStatus.Buffer, - LoRaMacUplinkStatus.BufferSize - ); - return false; - } - LoRaMacStatus_toString(status, str); - vt.SetCursorPos( 44, 1 ); - vt.printf("%u sendFrame() %s\e[K", sendCnt, str); - return true; -} void LoRaMacEventInfoStatus_toString(LoRaMacEventInfoStatus_t s, char* out) { @@ -597,7 +609,7 @@ char str[48]; LoRaMacEventInfoStatus_toString(mcpsIndication->Status, str); vt.SetCursorPos( 44, 1 ); - vt.printf("mcpsInd %s", str); + vt.printf("mcpsInd %s\e[K", str); return; } @@ -680,9 +692,9 @@ ( mcpsIndication->Buffer[1] == 0x01 ) && ( mcpsIndication->Buffer[2] == 0x01 ) && ( mcpsIndication->Buffer[3] == 0x01 ) ) { - IsTxConfirmed = false; + gIsTxConfirmed = false; AppPort = 224; - AppDataSize = 2; + gAppDataSize = 2; ComplianceTest.DownLinkCounter = 0; ComplianceTest.LinkCheck = false; ComplianceTest.DemodMargin = 0; @@ -703,9 +715,9 @@ ComplianceTest.State = mcpsIndication->Buffer[0]; switch( ComplianceTest.State ) { case 0: // Check compliance test disable command (ii) - IsTxConfirmed = LORAWAN_CONFIRMED_MSG_ON; + gIsTxConfirmed = LORAWAN_CONFIRMED_MSG_ON; AppPort = LORAWAN_APP_PORT; - AppDataSize = LORAWAN_APP_DATA_SIZE; + gAppDataSize = LORAWAN_APP_DATA_SIZE; ComplianceTest.DownLinkCounter = 0; ComplianceTest.Running = false; @@ -718,21 +730,21 @@ #endif break; case 1: // (iii, iv) - AppDataSize = 2; + gAppDataSize = 2; break; case 2: // Enable confirmed messages (v) - IsTxConfirmed = true; + gIsTxConfirmed = true; ComplianceTest.State = 1; break; case 3: // Disable confirmed messages (vi) - IsTxConfirmed = false; + gIsTxConfirmed = false; ComplianceTest.State = 1; break; case 4: // (vii) - AppDataSize = mcpsIndication->BufferSize; + gAppDataSize = mcpsIndication->BufferSize; AppData[0] = 4; - for( uint8_t i = 1; i < AppDataSize; i++ ) { + for( uint8_t i = 1; i < gAppDataSize; i++ ) { AppData[i] = mcpsIndication->Buffer[i] + 1; } break; @@ -746,9 +758,9 @@ MlmeReq_t mlmeReq; // Disable TestMode and revert back to normal operation - IsTxConfirmed = LORAWAN_CONFIRMED_MSG_ON; + gIsTxConfirmed = LORAWAN_CONFIRMED_MSG_ON; AppPort = LORAWAN_APP_PORT; - AppDataSize = LORAWAN_APP_DATA_SIZE; + gAppDataSize = LORAWAN_APP_DATA_SIZE; ComplianceTest.DownLinkCounter = 0; ComplianceTest.Running = false; @@ -852,8 +864,17 @@ void foo() { + float R, temp; + uint16_t u16; + vt.SetCursorPos( 43, 1 ); - vt.printf("%u d9:%u (%04x %04x %04x %04x)\e[K", DeviceState, d8.read(), a1.read_u16(), a2.read_u16(), a3.read_u16(), a4.read_u16()); + + u16 = a3.read_u16() >> 4; + R = 4096.0 / u16 - 1.0; + R = R0 * R; + temp = 1.0/(log(R/R0)/B+1/298.15)-273.15; + + vt.printf("%u d9:%u (%03x %03x %03x %03x) %.2fC\e[K\r\n", DeviceState, d8.read() >> 4, a1.read_u16() >> 4, a2.read_u16() >> 4, a3.read_u16() >> 4, a4.read_u16(), temp); } const LoRaMacPrimitives_t LoRaMacPrimitives = { @@ -1018,7 +1039,7 @@ SerialDisplayUpdateDonwlinkRxData( false ); PrepareTxFrame( AppPort ); - SendFrame( ); + SendFrame(gAppDataSize, gIsTxConfirmed); DeviceState = DEVICE_STATE_SLEEP; break;