diff --git a/features/lorawan/LoRaWANInterface.h b/features/lorawan/LoRaWANInterface.h index 3a0712ed19..b181ca1046 100644 --- a/features/lorawan/LoRaWANInterface.h +++ b/features/lorawan/LoRaWANInterface.h @@ -34,6 +34,7 @@ public: * */ LoRaWANInterface(LoRaRadio& radio); + virtual ~LoRaWANInterface(); /** Initialize the LoRa stack. diff --git a/features/lorawan/LoRaWANStack.cpp b/features/lorawan/LoRaWANStack.cpp index 7745a07f5a..a82c47efe8 100644 --- a/features/lorawan/LoRaWANStack.cpp +++ b/features/lorawan/LoRaWANStack.cpp @@ -175,90 +175,6 @@ lorawan_status_t LoRaWANStack::initialize_mac_layer(EventQueue *queue) return lora_state_machine(); } -#if defined(LORAWAN_COMPLIANCE_TEST) -/** - * - * Prepares the upload message to reserved ports - * - * \param port Application port - */ -void LoRaWANStack::prepare_special_tx_frame(uint8_t port) -{ - if (port == 224) { - // Clear any normal message stuff before compliance test. - memset(&_tx_msg, 0, sizeof(_tx_msg)); - - if (_compliance_test.link_check == true) { - _compliance_test.link_check = false; - _compliance_test.state = 1; - _tx_msg.f_buffer_size = 3; - _tx_msg.f_buffer[0] = 5; - _tx_msg.f_buffer[1] = _compliance_test.demod_margin; - _tx_msg.f_buffer[2] = _compliance_test.nb_gateways; - } else { - switch (_compliance_test.state) { - case 4: - _compliance_test.state = 1; - _tx_msg.f_buffer_size = _compliance_test.app_data_size; - - _tx_msg.f_buffer[0] = _compliance_test.app_data_buffer[0]; - for(uint8_t i = 1; i < MIN(_compliance_test.app_data_size, MBED_CONF_LORA_TX_MAX_SIZE); ++i) { - _tx_msg.f_buffer[i] = _compliance_test.app_data_buffer[i]; - } - break; - case 1: - _tx_msg.f_buffer_size = 2; - _tx_msg.f_buffer[0] = _compliance_test.downlink_counter >> 8; - _tx_msg.f_buffer[1] = _compliance_test.downlink_counter; - break; - } - } - } -} - -/** Hands over the compliance test frame to MAC layer - * - * \return returns the state of the LoRa MAC - */ -lorawan_status_t LoRaWANStack::send_compliance_test_frame_to_mac() -{ - loramac_mcps_req_t mcps_req; - - prepare_special_tx_frame(_compliance_test.app_port); - - if (!_compliance_test.is_tx_confirmed) { - mcps_req.type = MCPS_UNCONFIRMED; - mcps_req.req.unconfirmed.fport = _compliance_test.app_port; - mcps_req.f_buffer = _tx_msg.f_buffer; - mcps_req.f_buffer_size = _tx_msg.f_buffer_size; - mcps_req.req.unconfirmed.data_rate = _lora_phy.get_default_tx_datarate(); - - tr_info("Transmit unconfirmed compliance test frame %d bytes.", mcps_req.f_buffer_size); - - for (uint8_t i = 0; i < mcps_req.f_buffer_size; ++i) { - tr_info("Byte %d, data is 0x%x", i+1, ((uint8_t*)mcps_req.f_buffer)[i]); - } - } else if (_compliance_test.is_tx_confirmed) { - mcps_req.type = MCPS_CONFIRMED; - mcps_req.req.confirmed.fport = _compliance_test.app_port; - mcps_req.f_buffer = _tx_msg.f_buffer; - mcps_req.f_buffer_size = _tx_msg.f_buffer_size; - mcps_req.req.confirmed.nb_trials = _num_retry; - mcps_req.req.confirmed.data_rate = _lora_phy.get_default_tx_datarate(); - - tr_info("Transmit confirmed compliance test frame %d bytes.", mcps_req.f_buffer_size); - - for (uint8_t i = 0; i < mcps_req.f_buffer_size; ++i) { - tr_info("Byte %d, data is 0x%x", i+1, ((uint8_t*)mcps_req.f_buffer)[i]); - } - } else { - return LORAWAN_STATUS_SERVICE_UNKNOWN; - } - - return mcps_request_handler(&mcps_req); -} -#endif - uint16_t LoRaWANStack::check_possible_tx_size(uint16_t size) { loramac_tx_info_t tx_info; @@ -284,43 +200,45 @@ lorawan_status_t LoRaWANStack::send_frame_to_mac() mcps_req.type = _tx_msg.type; if (MCPS_UNCONFIRMED == mcps_req.type) { - mcps_req.req.unconfirmed.fport = _tx_msg.message_u.unconfirmed.fport; mcps_req.f_buffer = _tx_msg.f_buffer; - mcps_req.f_buffer_size = _tx_msg.f_buffer_size; + mcps_req.fport = _tx_msg.fport; + mcps_req.nb_trials = 1; mib_get_params.type = MIB_CHANNELS_DATARATE; if(mib_get_request(&mib_get_params) != LORAWAN_STATUS_OK) { tr_debug("Couldn't get MIB parameters: Using default data rate"); - mcps_req.req.unconfirmed.data_rate = _lora_phy.get_default_tx_datarate(); + mcps_req.data_rate = _lora_phy.get_default_tx_datarate(); } else { - mcps_req.req.unconfirmed.data_rate = mib_get_params.param.channel_data_rate; + mcps_req.data_rate = mib_get_params.param.channel_data_rate; } } else if (mcps_req.type == MCPS_CONFIRMED) { - mcps_req.req.confirmed.fport = _tx_msg.message_u.confirmed.fport; mcps_req.f_buffer = _tx_msg.f_buffer; mcps_req.f_buffer_size = _tx_msg.f_buffer_size; - mcps_req.req.confirmed.nb_trials = _tx_msg.message_u.confirmed.nb_trials; + mcps_req.fport = _tx_msg.fport; + mcps_req.nb_trials = _tx_msg.nb_trials; mib_get_params.type = MIB_CHANNELS_DATARATE; if(mib_get_request(&mib_get_params) != LORAWAN_STATUS_OK) { tr_debug("Couldn't get MIB parameters: Using default data rate"); - mcps_req.req.confirmed.data_rate = _lora_phy.get_default_tx_datarate(); + mcps_req.data_rate = _lora_phy.get_default_tx_datarate(); } else { - mcps_req.req.confirmed.data_rate = mib_get_params.param.channel_data_rate; + mcps_req.data_rate = mib_get_params.param.channel_data_rate; } } else if ( mcps_req.type == MCPS_PROPRIETARY) { mcps_req.f_buffer = _tx_msg.f_buffer; mcps_req.f_buffer_size = _tx_msg.f_buffer_size; + mcps_req.fport = 0; + mcps_req.nb_trials = 1; mib_get_params.type = MIB_CHANNELS_DATARATE; if(mib_get_request(&mib_get_params) != LORAWAN_STATUS_OK) { tr_debug("Couldn't get MIB parameters: Using default data rate"); - mcps_req.req.proprietary.data_rate = _lora_phy.get_default_tx_datarate(); + mcps_req.data_rate = _lora_phy.get_default_tx_datarate(); } else { - mcps_req.req.proprietary.data_rate = mib_get_params.param.channel_data_rate; + mcps_req.data_rate = mib_get_params.param.channel_data_rate; } } else { @@ -651,7 +569,7 @@ int16_t LoRaWANStack::handle_tx(uint8_t port, const uint8_t* data, || (flags & MSG_FLAG_MASK) == MSG_UNCONFIRMED_PROPRIETARY) { _tx_msg.type = MCPS_UNCONFIRMED; - _tx_msg.message_u.unconfirmed.fport = _app_port; + _tx_msg.fport = _app_port; } // Handles all confirmed messages, including proprietary and multicast @@ -660,8 +578,8 @@ int16_t LoRaWANStack::handle_tx(uint8_t port, const uint8_t* data, || (flags & MSG_FLAG_MASK) == MSG_CONFIRMED_PROPRIETARY) { _tx_msg.type = MCPS_CONFIRMED; - _tx_msg.message_u.confirmed.fport = _app_port; - _tx_msg.message_u.confirmed.nb_trials = _num_retry; + _tx_msg.fport = _app_port; + _tx_msg.nb_trials = _num_retry; } tr_info("RTS = %u bytes, PEND = %u", _tx_msg.f_buffer_size, _tx_msg.pending_size); @@ -1357,3 +1275,89 @@ lorawan_status_t LoRaWANStack::lora_state_machine() return status; } + +#if defined(LORAWAN_COMPLIANCE_TEST) +/** + * + * Prepares the upload message to reserved ports + * + * \param port Application port + */ +void LoRaWANStack::prepare_special_tx_frame(uint8_t port) +{ + if (port == 224) { + // Clear any normal message stuff before compliance test. + memset(&_tx_msg, 0, sizeof(_tx_msg)); + + if (_compliance_test.link_check == true) { + _compliance_test.link_check = false; + _compliance_test.state = 1; + _tx_msg.f_buffer_size = 3; + _tx_msg.f_buffer[0] = 5; + _tx_msg.f_buffer[1] = _compliance_test.demod_margin; + _tx_msg.f_buffer[2] = _compliance_test.nb_gateways; + } else { + switch (_compliance_test.state) { + case 4: + _compliance_test.state = 1; + _tx_msg.f_buffer_size = _compliance_test.app_data_size; + + _tx_msg.f_buffer[0] = _compliance_test.app_data_buffer[0]; + for(uint8_t i = 1; i < MIN(_compliance_test.app_data_size, MBED_CONF_LORA_TX_MAX_SIZE); ++i) { + _tx_msg.f_buffer[i] = _compliance_test.app_data_buffer[i]; + } + break; + case 1: + _tx_msg.f_buffer_size = 2; + _tx_msg.f_buffer[0] = _compliance_test.downlink_counter >> 8; + _tx_msg.f_buffer[1] = _compliance_test.downlink_counter; + break; + } + } + } +} + +/** Hands over the compliance test frame to MAC layer + * + * \return returns the state of the LoRa MAC + */ +lorawan_status_t LoRaWANStack::send_compliance_test_frame_to_mac() +{ + loramac_mcps_req_t mcps_req; + + prepare_special_tx_frame(_compliance_test.app_port); + + if (!_compliance_test.is_tx_confirmed) { + mcps_req.type = MCPS_UNCONFIRMED; + mcps_req.f_buffer = _tx_msg.f_buffer; + mcps_req.f_buffer_size = _tx_msg.f_buffer_size; + mcps_req.fport = _compliance_test.app_port; + mcps_req.nb_trials = 1; + mcps_req.data_rate = _lora_phy.get_default_tx_datarate(); + + tr_info("Transmit unconfirmed compliance test frame %d bytes.", mcps_req.f_buffer_size); + + for (uint8_t i = 0; i < mcps_req.f_buffer_size; ++i) { + tr_info("Byte %d, data is 0x%x", i+1, ((uint8_t*)mcps_req.f_buffer)[i]); + } + } else if (_compliance_test.is_tx_confirmed) { + mcps_req.type = MCPS_CONFIRMED; + mcps_req.f_buffer = _tx_msg.f_buffer; + mcps_req.f_buffer_size = _tx_msg.f_buffer_size; + mcps_req.fport = _compliance_test.app_port; + mcps_req.nb_trials = _num_retry; + mcps_req.data_rate = _lora_phy.get_default_tx_datarate(); + + tr_info("Transmit confirmed compliance test frame %d bytes.", mcps_req.f_buffer_size); + + for (uint8_t i = 0; i < mcps_req.f_buffer_size; ++i) { + tr_info("Byte %d, data is 0x%x", i+1, ((uint8_t*)mcps_req.f_buffer)[i]); + } + } else { + return LORAWAN_STATUS_SERVICE_UNKNOWN; + } + + return mcps_request_handler(&mcps_req); +} +#endif + diff --git a/features/lorawan/LoRaWANStack.h b/features/lorawan/LoRaWANStack.h index 08daf98ca9..1f07d1c9b9 100644 --- a/features/lorawan/LoRaWANStack.h +++ b/features/lorawan/LoRaWANStack.h @@ -77,6 +77,24 @@ SPDX-License-Identifier: BSD-3-Clause #define LORAWAN_NETWORK_ID_MASK ( uint32_t )0xFE000000 class LoRaWANStack: private mbed::NonCopyable { +private: + /** End-device states. + * + */ + typedef enum device_states { + DEVICE_STATE_NOT_INITIALIZED, + DEVICE_STATE_INIT, + DEVICE_STATE_JOINING, + DEVICE_STATE_ABP_CONNECTING, + DEVICE_STATE_JOINED, + DEVICE_STATE_SEND, + DEVICE_STATE_IDLE, +#if defined(LORAWAN_COMPLIANCE_TEST) + DEVICE_STATE_COMPLIANCE_TEST, +#endif + DEVICE_STATE_SHUTDOWN + } device_states_t; + public: static LoRaWANStack& get_lorawan_stack(); @@ -424,6 +442,25 @@ private: */ uint16_t check_possible_tx_size(uint16_t size); +private: + + LoRaWANTimeHandler _lora_time; + LoRaMac _loramac; + LoRaPHY_region _lora_phy; + loramac_primitives_t LoRaMacPrimitives; + + device_states_t _device_current_state; + lorawan_app_callbacks_t _callbacks; + radio_events_t *_mac_handlers; + lorawan_session_t _lw_session; + loramac_tx_message_t _tx_msg; + loramac_rx_message_t _rx_msg; + uint8_t _app_port; + uint8_t _num_retry; + events::EventQueue *_queue; + bool _duty_cycle_on; + + #if defined(LORAWAN_COMPLIANCE_TEST) /** * This function is used only for compliance testing @@ -439,28 +476,10 @@ private: * Used only for compliance testing */ lorawan_status_t send_compliance_test_frame_to_mac(); -#endif - LoRaWANTimeHandler _lora_time; - LoRaMac _loramac; - LoRaPHY_region _lora_phy; - loramac_primitives_t LoRaMacPrimitives; - -#if defined(LORAWAN_COMPLIANCE_TEST) uint8_t compliance_test_buffer[MBED_CONF_LORA_TX_MAX_SIZE]; compliance_test_t _compliance_test; #endif - - device_states_t _device_current_state; - lorawan_app_callbacks_t _callbacks; - radio_events_t *_mac_handlers; - lorawan_session_t _lw_session; - loramac_tx_message_t _tx_msg; - loramac_rx_message_t _rx_msg; - uint8_t _app_port; - uint8_t _num_retry; - events::EventQueue *_queue; - bool _duty_cycle_on; }; #endif /* LORAWANSTACK_H_ */ diff --git a/features/lorawan/lorastack/mac/LoRaMac.cpp b/features/lorawan/lorastack/mac/LoRaMac.cpp index 2d9db80e49..0fb4dd3f18 100644 --- a/features/lorawan/lorastack/mac/LoRaMac.cpp +++ b/features/lorawan/lorastack/mac/LoRaMac.cpp @@ -1609,7 +1609,7 @@ lorawan_status_t LoRaMac::initialize(loramac_primitives_t *primitives, mlme.activate_mlme_subsystem(lora_phy); // Activate MCPS subsystem - mcps.activate_mcps_subsystem(this, lora_phy); + mcps.activate_mcps_subsystem(); // Activate MIB subsystem mib.activate_mib_subsystem(lora_phy); @@ -1955,7 +1955,60 @@ lorawan_status_t LoRaMac::mcps_request( loramac_mcps_req_t *mcpsRequest ) return LORAWAN_STATUS_BUSY; } - lorawan_status_t status = mcps.set_request(mcpsRequest, &_params); + loramac_mhdr_t machdr; + int8_t datarate = mcpsRequest->data_rate; + // TODO: The comment is different than the code??? + // Apply the minimum possible datarate. + // Some regions have limitations for the minimum datarate. + datarate = MAX(datarate, (int8_t)lora_phy->get_minimum_tx_datarate()); + + machdr.value = 0; + + mcps.reset_confirmation(); + + _params.ack_timeout_retry_counter = 1; + _params.max_ack_timeout_retries = 1; + + switch (mcpsRequest->type) { + case MCPS_UNCONFIRMED: { + machdr.bits.mtype = FRAME_TYPE_DATA_UNCONFIRMED_UP; + break; + } + case MCPS_CONFIRMED: { + machdr.bits.mtype = FRAME_TYPE_DATA_CONFIRMED_UP; + _params.max_ack_timeout_retries = mcpsRequest->nb_trials; + break; + } + case MCPS_PROPRIETARY: { + machdr.bits.mtype = FRAME_TYPE_PROPRIETARY; + break; + } + default: + return LORAWAN_STATUS_PARAMETER_INVALID; + } + +// Filter fPorts +// TODO: Does not work with PROPRIETARY messages +// if( IsFPortAllowed( mcpsRequest->fport ) == false ) { +// return LORAWAN_STATUS_PARAMETER_INVALID; +// } + + if (_params.sys_params.adr_on == false) { + if (lora_phy->verify_tx_datarate(datarate, false) == true) { + _params.sys_params.channel_data_rate = datarate; + } else { + return LORAWAN_STATUS_PARAMETER_INVALID; + } + } + + lorawan_status_t status = send(&machdr, mcpsRequest->fport, mcpsRequest->f_buffer, + mcpsRequest->f_buffer_size); + if (status == LORAWAN_STATUS_OK) { + mcps.get_confirmation().req_type = mcpsRequest->type; + _params.flags.bits.mcps_req = 1; + } else { + _params.is_node_ack_requested = false; + } return status; } diff --git a/features/lorawan/lorastack/mac/LoRaMac.h b/features/lorawan/lorastack/mac/LoRaMac.h index b1676f8489..73d352c793 100644 --- a/features/lorawan/lorastack/mac/LoRaMac.h +++ b/features/lorawan/lorastack/mac/LoRaMac.h @@ -334,9 +334,9 @@ public: * * loramac_mcps_req_t request; * request.type = MCPS_UNCONFIRMED; - * request.req.unconfirmed.fport = 1; - * request.req.unconfirmed.f_buffer = buffer; - * request.req.unconfirmed.f_buffer_size = sizeof(buffer); + * request.fport = 1; + * request.f_buffer = buffer; + * request.f_buffer_size = sizeof(buffer); * * if (mcps_request(&request) == LORAWAN_STATUS_OK) { * // Service started successfully. Waiting for the MCPS-Confirm event @@ -427,79 +427,7 @@ public: */ void open_continuous_rx2_window(void); -#if defined(LORAWAN_COMPLIANCE_TEST) -public: // Test interface - /** - * \brief LoRaMAC set tx timer. - * - * \details Sets up a timer for next transmission (application specific timers). - * - * \param [in] NextTxTime - Periodic time for next uplink. - - * \retval `lorawan_status_t` The status of the operation. The possible values are: - * \ref LORAWAN_STATUS_OK - * \ref LORAWAN_STATUS_PARAMETER_INVALID - */ - lorawan_status_t LoRaMacSetTxTimer( uint32_t NextTxTime ); - - /** - * \brief LoRaMAC stop tx timer. - * - * \details Stops the next tx timer. - * - * \retval `lorawan_status_t` The status of the operation. The possible values are: - * \ref LORAWAN_STATUS_OK - * \ref LORAWAN_STATUS_PARAMETER_INVALID - */ - lorawan_status_t LoRaMacStopTxTimer( ); - - /** - * \brief Enabled or disables the reception windows - * - * \details This is a test function. It shall be used for testing purposes only. - * Changing this attribute may lead to a non-conformance LoRaMac operation. - * - * \param [in] enable - Enabled or disables the reception windows - */ - void LoRaMacTestRxWindowsOn( bool enable ); - - /** - * \brief Enables the MIC field test - * - * \details This is a test function. It shall be used for testing purposes only. - * Changing this attribute may lead to a non-conformance LoRaMac operation. - * - * \param [in] txPacketCounter - Fixed Tx packet counter value - */ - void LoRaMacTestSetMic( uint16_t txPacketCounter ); - - /** - * \brief Enabled or disables the duty cycle - * - * \details This is a test function. It shall be used for testing purposes only. - * Changing this attribute may lead to a non-conformance LoRaMac operation. - * - * \param [in] enable - Enabled or disables the duty cycle - */ - void LoRaMacTestSetDutyCycleOn( bool enable ); - - /** - * \brief Sets the channel index - * - * \details This is a test function. It shall be used for testing purposes only. - * Changing this attribute may lead to a non-conformance LoRaMac operation. - * - * \param [in] channel - Channel index - */ - void LoRaMacTestSetChannel( uint8_t channel ); - -private: - /** - * Timer to handle the application data transmission duty cycle - */ - timer_event_t tx_next_packet_timer; -#endif private: /** @@ -673,6 +601,80 @@ private: * EventQueue object storage */ events::EventQueue *ev_queue; + +#if defined(LORAWAN_COMPLIANCE_TEST) +public: // Test interface + + /** + * \brief LoRaMAC set tx timer. + * + * \details Sets up a timer for next transmission (application specific timers). + * + * \param [in] NextTxTime - Periodic time for next uplink. + + * \retval `lorawan_status_t` The status of the operation. The possible values are: + * \ref LORAWAN_STATUS_OK + * \ref LORAWAN_STATUS_PARAMETER_INVALID + */ + lorawan_status_t LoRaMacSetTxTimer( uint32_t NextTxTime ); + + /** + * \brief LoRaMAC stop tx timer. + * + * \details Stops the next tx timer. + * + * \retval `lorawan_status_t` The status of the operation. The possible values are: + * \ref LORAWAN_STATUS_OK + * \ref LORAWAN_STATUS_PARAMETER_INVALID + */ + lorawan_status_t LoRaMacStopTxTimer( ); + + /** + * \brief Enabled or disables the reception windows + * + * \details This is a test function. It shall be used for testing purposes only. + * Changing this attribute may lead to a non-conformance LoRaMac operation. + * + * \param [in] enable - Enabled or disables the reception windows + */ + void LoRaMacTestRxWindowsOn( bool enable ); + + /** + * \brief Enables the MIC field test + * + * \details This is a test function. It shall be used for testing purposes only. + * Changing this attribute may lead to a non-conformance LoRaMac operation. + * + * \param [in] txPacketCounter - Fixed Tx packet counter value + */ + void LoRaMacTestSetMic( uint16_t txPacketCounter ); + + /** + * \brief Enabled or disables the duty cycle + * + * \details This is a test function. It shall be used for testing purposes only. + * Changing this attribute may lead to a non-conformance LoRaMac operation. + * + * \param [in] enable - Enabled or disables the duty cycle + */ + void LoRaMacTestSetDutyCycleOn( bool enable ); + + /** + * \brief Sets the channel index + * + * \details This is a test function. It shall be used for testing purposes only. + * Changing this attribute may lead to a non-conformance LoRaMac operation. + * + * \param [in] channel - Channel index + */ + void LoRaMacTestSetChannel( uint8_t channel ); + +private: + /** + * Timer to handle the application data transmission duty cycle + */ + timer_event_t tx_next_packet_timer; +#endif }; #endif // MBED_LORAWAN_MAC_H__ diff --git a/features/lorawan/lorastack/mac/LoRaMacMcps.cpp b/features/lorawan/lorastack/mac/LoRaMacMcps.cpp index 28832c4af5..ab340e10d0 100644 --- a/features/lorawan/lorastack/mac/LoRaMacMcps.cpp +++ b/features/lorawan/lorastack/mac/LoRaMacMcps.cpp @@ -27,7 +27,6 @@ SPDX-License-Identifier: BSD-3-Clause #include "lorastack/mac/LoRaMacMcps.h" LoRaMacMcps::LoRaMacMcps() -: _lora_mac(NULL), _lora_phy(NULL) { } @@ -35,6 +34,13 @@ LoRaMacMcps::~LoRaMacMcps() { } +void LoRaMacMcps::reset_confirmation() +{ + memset((uint8_t*) &confirmation, 0, sizeof(confirmation)); + + confirmation.status = LORAMAC_EVENT_INFO_STATUS_ERROR; +} + loramac_mcps_confirm_t& LoRaMacMcps::get_confirmation() { return confirmation; @@ -45,104 +51,7 @@ loramac_mcps_indication_t& LoRaMacMcps::get_indication() return indication; } -void LoRaMacMcps::activate_mcps_subsystem(LoRaMac *mac, LoRaPHY *phy) +void LoRaMacMcps::activate_mcps_subsystem() { - _lora_mac = mac; - _lora_phy = phy; } -lorawan_status_t LoRaMacMcps::set_request(loramac_mcps_req_t *mcpsRequest, - loramac_protocol_params *params) -{ - - if (mcpsRequest == NULL || _lora_phy == NULL || _lora_mac == NULL) { - return LORAWAN_STATUS_PARAMETER_INVALID; - } - - lorawan_status_t status = LORAWAN_STATUS_SERVICE_UNKNOWN; - loramac_mhdr_t machdr; - uint8_t fport = 0; - void *fbuffer; - uint16_t fbuffer_size; - int8_t datarate = DR_0; - bool ready_to_send = false; - - machdr.value = 0; - - // Before performing any MCPS request, clear the confirmation structure - memset((uint8_t*) &confirmation, 0, sizeof(confirmation)); - - confirmation.status = LORAMAC_EVENT_INFO_STATUS_ERROR; - - // ack_timeout_retry_counter must be reset every time a new request (unconfirmed or confirmed) is performed. - params->ack_timeout_retry_counter = 1; - - switch (mcpsRequest->type) { - case MCPS_UNCONFIRMED: { - ready_to_send = true; - params->max_ack_timeout_retries = 1; - - machdr.bits.mtype = FRAME_TYPE_DATA_UNCONFIRMED_UP; - fport = mcpsRequest->req.unconfirmed.fport; - fbuffer = mcpsRequest->f_buffer; - fbuffer_size = mcpsRequest->f_buffer_size; - datarate = mcpsRequest->req.unconfirmed.data_rate; - break; - } - case MCPS_CONFIRMED: { - ready_to_send = true; - params->max_ack_timeout_retries = mcpsRequest->req.confirmed.nb_trials; - - machdr.bits.mtype = FRAME_TYPE_DATA_CONFIRMED_UP; - fport = mcpsRequest->req.confirmed.fport; - fbuffer = mcpsRequest->f_buffer; - fbuffer_size = mcpsRequest->f_buffer_size; - datarate = mcpsRequest->req.confirmed.data_rate; - break; - } - case MCPS_PROPRIETARY: { - ready_to_send = true; - params->max_ack_timeout_retries = 1; - - machdr.bits.mtype = FRAME_TYPE_PROPRIETARY; - fbuffer = mcpsRequest->f_buffer; - fbuffer_size = mcpsRequest->f_buffer_size; - datarate = mcpsRequest->req.proprietary.data_rate; - break; - } - default: - break; - } - - // Filter fPorts - // TODO: Does not work with PROPRIETARY messages - // if( IsFPortAllowed( fPort ) == false ) - // { - // return LORAWAN_STATUS_PARAMETER_INVALID; - // } - - // Apply the minimum possible datarate. - // Some regions have limitations for the minimum datarate. - datarate = MAX(datarate, (int8_t)_lora_phy->get_minimum_tx_datarate()); - - if (ready_to_send == true) { - if (params->sys_params.adr_on == false) { - if (_lora_phy->verify_tx_datarate(datarate, false) == true) { - params->sys_params.channel_data_rate = datarate; - } else { - return LORAWAN_STATUS_PARAMETER_INVALID; - } - } - - //nämä lora_maciin - status = _lora_mac->send(&machdr, fport, fbuffer, fbuffer_size); - if (status == LORAWAN_STATUS_OK) { - confirmation.req_type = mcpsRequest->type; - params->flags.bits.mcps_req = 1; - } else { - params->is_node_ack_requested = false; - } - } - - return status; -} diff --git a/features/lorawan/lorastack/mac/LoRaMacMcps.h b/features/lorawan/lorastack/mac/LoRaMacMcps.h index 655c94d036..8d7819d514 100644 --- a/features/lorawan/lorastack/mac/LoRaMacMcps.h +++ b/features/lorawan/lorastack/mac/LoRaMacMcps.h @@ -49,6 +49,11 @@ public: */ ~LoRaMacMcps(); + /** + * @brief reset_confirmation Resets the confirmation struct + */ + void reset_confirmation(); + /** Activating MCPS subsystem * * Stores pointers to MAC and PHY layer handles @@ -56,21 +61,7 @@ public: * @param mac pointer to MAC layer * @param phy pointer to PHY layer */ - void activate_mcps_subsystem(LoRaMac *mac, LoRaPHY *phy); - - /** Sets up an MCPS Request - * - * Sets up an MCPS request and sends it through to the central MAC control. - * It also modifies or uses protocol information provided in the MAC - * protocol data structure. - * - * @param mcpsRequest pointer to MCPS request structure - * @param params pointer to MAC protocol parameters - * - * @return LORAWAN_STATUS_OK if everything goes well otherwise - * a negative error code is returned. - */ - lorawan_status_t set_request(loramac_mcps_req_t *mcpsRequest, loramac_protocol_params *params); + void activate_mcps_subsystem(); /** Grants access to MCPS confirmation data * @@ -86,12 +77,6 @@ public: private: - /** - * Pointers to MAC and PHY handles - */ - LoRaMac *_lora_mac; - LoRaPHY *_lora_phy; - /** * Structure to hold MCPS indication data. */ diff --git a/features/lorawan/lorastack/mac/LoRaMacMlme.h b/features/lorawan/lorastack/mac/LoRaMacMlme.h index 06ea8a43fc..ceb1f2b7cd 100644 --- a/features/lorawan/lorastack/mac/LoRaMacMlme.h +++ b/features/lorawan/lorastack/mac/LoRaMacMlme.h @@ -49,6 +49,9 @@ public: */ ~LoRaMacMlme(); + /** + * @brief reset_confirmation Resets the confirmation struct + */ void reset_confirmation(); /** Activating MLME subsystem diff --git a/features/lorawan/system/lorawan_data_structures.h b/features/lorawan/system/lorawan_data_structures.h index cc37cf0178..2c8d357f3f 100644 --- a/features/lorawan/system/lorawan_data_structures.h +++ b/features/lorawan/system/lorawan_data_structures.h @@ -763,27 +763,14 @@ typedef enum { } mcps_type_t; /*! - * LoRaMAC MCPS-Request for an unconfirmed frame. + * LoRaMAC MCPS-Request structure. */ typedef struct { /*! - * Frame port field. Must be set if the payload is not empty. Use the - * application-specific frame port values: [1...223]. - * - * LoRaWAN Specification V1.0.2, chapter 4.3.2. + * MCPS-Request type. */ - uint8_t fport; + mcps_type_t type; - /*! - * Uplink datarate, if ADR is off. - */ - int8_t data_rate; -} mcps_req_unconfirmed_t; - -/*! - * LoRaMAC MCPS-Request for a confirmed frame. - */ -typedef struct { /*! * Frame port field. Must be set if the payload is not empty. Use the * application-specific frame port values: [1...223]. @@ -817,45 +804,6 @@ typedef struct { * the datarate, if the LoRaMAC layer did not receive an acknowledgment. */ uint8_t nb_trials; -} mcps_req_confirmed_t; - -/*! - * LoRaMAC MCPS-Request for a proprietary frame. - */ -typedef struct { - /*! - * Uplink datarate, if ADR is off. - */ - int8_t data_rate; -} mcps_req_proprietary_t; - -/*! - * LoRaMAC MCPS-Request structure. - */ -typedef struct { - /*! - * MCPS-Request type. - */ - mcps_type_t type; - - /*! - * MCPS-Request parameters. - */ - union - { - /*! - * MCPS-Request parameters for an unconfirmed frame. - */ - mcps_req_unconfirmed_t unconfirmed; - /*! - * MCPS-Request parameters for a confirmed frame. - */ - mcps_req_confirmed_t confirmed; - /*! - * MCPS-Request parameters for a proprietary frame. - */ - mcps_req_proprietary_t proprietary; - } req; /** Payload data * @@ -1663,23 +1611,6 @@ typedef struct { mbed::Callback mlme_indication; }loramac_primitives_t; -/** End-device states. - * - */ -typedef enum device_states { - DEVICE_STATE_NOT_INITIALIZED, - DEVICE_STATE_INIT, - DEVICE_STATE_JOINING, - DEVICE_STATE_ABP_CONNECTING, - DEVICE_STATE_JOINED, - DEVICE_STATE_SEND, - DEVICE_STATE_IDLE, -#if defined(LORAWAN_COMPLIANCE_TEST) - DEVICE_STATE_COMPLIANCE_TEST, -#endif - DEVICE_STATE_SHUTDOWN -} device_states_t; - /** Enum of LoRaWAN connection type. * * The LoRaWAN connection type specifies how an end-device connects to the gateway. @@ -1764,26 +1695,40 @@ typedef struct { * Message type */ mcps_type_t type; - /** Message parameters. + + /*! + * Frame port field. Must be set if the payload is not empty. Use the + * application-specific frame port values: [1...223]. * + * LoRaWAN Specification V1.0.2, chapter 4.3.2. */ - union message { - /** An unconfirmed frame. - * - * The message parameters for an unconfirmed frame. - */ - mcps_req_unconfirmed_t unconfirmed; - /** A confirmed frame. - * - * The message parameters for a confirmed frame. - */ - mcps_req_confirmed_t confirmed; - /** A proprietary frame. - * - * The message parameters for a proprietary frame. - */ - mcps_req_proprietary_t proprietary; - } message_u; + uint8_t fport; + + /*! + * Uplink datarate, if ADR is off. + */ + int8_t data_rate; + /*! + * The number of trials to transmit the frame, if the LoRaMAC layer did not + * receive an acknowledgment. The MAC performs a datarate adaptation + * according to the LoRaWAN Specification V1.0.2, chapter 18.4, as in + * the following table: + * + * Transmission nb | Data Rate + * ----------------|----------- + * 1 (first) | DR + * 2 | DR + * 3 | max(DR-1,0) + * 4 | max(DR-1,0) + * 5 | max(DR-2,0) + * 6 | max(DR-2,0) + * 7 | max(DR-3,0) + * 8 | max(DR-3,0) + * + * Note that if nb_trials is set to 1 or 2, the MAC will not decrease + * the datarate, if the LoRaMAC layer did not receive an acknowledgment. + */ + uint8_t nb_trials; /** Payload data * @@ -1918,54 +1863,6 @@ typedef struct { uint32_t downlink_counter; } lorawan_dev_commission_t; -#if defined(LORAWAN_COMPLIANCE_TEST) -/** LoRaWAN compliance tests support data - * - */ -typedef struct compliance_test { - /** Is test running - * - */ - bool running; - /** State of test - * - */ - uint8_t state; - /** Is TX confirmed - * - */ - bool is_tx_confirmed; - /** Port used by the application - * - */ - uint8_t app_port; - /** Maximum size of data used by application - * - */ - uint8_t app_data_size; - /** Data provided by application - * - */ - uint8_t *app_data_buffer; - /** Downlink counter - * - */ - uint16_t downlink_counter; - /** Is link check required - * - */ - bool link_check; - /** Demodulation margin - * - */ - uint8_t demod_margin; - /** Number of gateways - * - */ - uint8_t nb_gateways; -} compliance_test_t; -#endif - /** Structure containing the uplink status * */ @@ -2411,4 +2308,52 @@ typedef struct lora_channelplan { loramac_channel_t *channels; } lorawan_channelplan_t; +#if defined(LORAWAN_COMPLIANCE_TEST) +/** LoRaWAN compliance tests support data + * + */ +typedef struct compliance_test { + /** Is test running + * + */ + bool running; + /** State of test + * + */ + uint8_t state; + /** Is TX confirmed + * + */ + bool is_tx_confirmed; + /** Port used by the application + * + */ + uint8_t app_port; + /** Maximum size of data used by application + * + */ + uint8_t app_data_size; + /** Data provided by application + * + */ + uint8_t *app_data_buffer; + /** Downlink counter + * + */ + uint16_t downlink_counter; + /** Is link check required + * + */ + bool link_check; + /** Demodulation margin + * + */ + uint8_t demod_margin; + /** Number of gateways + * + */ + uint8_t nb_gateways; +} compliance_test_t; +#endif + #endif /* LORAWAN_SYSTEM_LORAWAN_DATA_STRUCTURES_H_ */