Prepare for deep sleep functions

This commit is contained in:
Manuel Bl 2021-09-26 16:35:42 +02:00
parent 1df2c50f6f
commit bd728887cf
3 changed files with 182 additions and 85 deletions

View File

@ -436,17 +436,6 @@ class TheThingsNetwork
{
}
/**
* @brief Resets the LoRaWAN radio.
*
* To restart communication, @ref join() must be called.
* Clears neither the provisioned keys nor the configured pins.
*/
void reset()
{
ttn_reset();
}
/**
* @brief Configures the pins used to communicate with the LoRaWAN radio chip.
*
@ -553,11 +542,14 @@ class TheThingsNetwork
}
/**
* @brief Activates the device via OTAA.
* @brief Activates the device via OTAA using previously provisioned keys.
*
* The DevEUI, AppEUI/JoinEUI and AppKey must have already been provisioned by a call to provision().
* The DevEUI, AppEUI/JoinEUI and AppKey must have already been provisioned by a call
* to @ref provision() or @ref provisionWithMAC().
* Before this function is called, `nvs_flash_init()` must have been called once.
*
* The RF module is initialized and the TTN background task is started.
*
* The function blocks until the activation has completed or failed.
*
* @return `true` if the activation was succesful, `false` if the activation failed
@ -568,9 +560,12 @@ class TheThingsNetwork
}
/**
* @brief Sets the DevEUI, AppEUI/JoinEUI and AppKey and activate the device via OTAA.
* @brief Activates the device via OTAA using the provided keys.
*
* The DevEUI, AppEUI/JoinEUI and AppKey are NOT saved in non-volatile memory.
* For the activation, the provided DevEUI, AppEUI/JoinEUI and AppKey are used.
* They are NOT saved in non-volatile memory.
*
* The RF module is initialized and the TTN background task is started.
*
* The function blocks until the activation has completed or failed.
*
@ -584,6 +579,78 @@ class TheThingsNetwork
return ttn_join(devEui, appEui, appKey);
}
/**
* @brief Resumes TTN communication after deep sleep.
*
* The communcation state is restored from data previously saved in RTC memory.
* The RF module and the TTN background task are started.
*
* This function is called instead of @ref join() or @ref join(const char*, const char*, const char*)
* to continue with the established communication and to avoid a further join procedure.
*
* @return `true` if the device was able to resume, `false` otherwise.
*/
bool resumeAfterDeepSleep()
{
return ttn_resume_after_deep_sleep();
}
/**
* @brief Stops all activies and prepares for deep sleep.
*
* This function is called before entering deep sleep. It saves the current
* communication state in RTC memory and shuts down the RF module and the
* TTN background task.
*
* It neither clears the provisioned keys nor the configured pins
* but they will be lost if the device goes into deep sleep.
*
* Before calling this function, use @ref busyDuration() to check
* that the TTN device is idle and ready to go to deep sleep.
*
* To restart communication, @ref resumeAfterDeepSleep() must be called.
*/
void prepareForDeepSleep()
{
ttn_prepare_for_deep_sleep();
}
/**
* @brief Returns the minimum duration the TTN device is busy.
*
* This function can be called to check whether the TTN device is
* still involved in communication or ready to go to deep sleep or
* to be powered off.
*
* If it returns 0, the TTN communication is idle and the device can go
* to deep sleep or can be powered off.
*
* If it returns a value different from 0, the value indicates the duration
* the device will be certainly busy. After that time, this function must be
* called again. It might still return a value different from 0.
*
* @return busy duration (in FreeRTOS ticks)
*/
TickType_t busyDuration()
{
return ttn_busy_duration();
}
/**
* @brief Stops all activies.
*
* This function shuts down the RF module and the TTN background task. It neither clears the
* provisioned keys nor the configured pins. The currentat device state (and activation)
* are lost.
*
* To restart communication, @ref join() or @ref join(const char*, const char*, const char*)
* must be called.
*/
void shutdown()
{
ttn_shutdown();
}
/**
* @brief Transmits a message
*
@ -697,27 +764,6 @@ class TheThingsNetwork
ttn_set_max_tx_pow(tx_pow);
}
/**
* @brief Stops all activies and shuts down the RF module and the background tasks.
*
* To restart communication, @ref startup() and @ref join() must be called.
* it neither clears the provisioned keys nor the configured pins.
*/
void shutdown()
{
ttn_shutdown();
}
/**
* @brief Restarts the background tasks and RF module.
*
* This member function must only be called after a call to shutdowna().
*/
void startup()
{
ttn_startup();
}
/**
* @brief Gets current RX/TX window
* @return window

View File

@ -432,19 +432,13 @@ extern "C"
*/
void ttn_init(void);
/**
* @brief Resets the LoRaWAN radio.
*
* To restart communication, @ref ttn_join() or @ref ttn_join_provisioned() must be called.
* It neither clears the provisioned keys nor the configured pins.
*/
void ttn_reset(void);
/**
* @brief Configures the pins used to communicate with the LoRaWAN radio chip.
*
* Before calling this member function, the SPI bus needs to be configured using `spi_bus_initialize()`.
* Additionally, `gpio_install_isr_service()` must have been called to initialize the GPIO ISR handler service.
*
* Call this function after @ref ttn_init() and before all other TTN functions.
*
* @param spi_host The SPI bus/peripherial to use (`SPI_HOST`, `HSPI_HOST` or `VSPI_HOST`).
* @param nss The GPIO pin number connected to the radio chip's NSS pin (serving as the SPI chip select)
@ -528,11 +522,14 @@ extern "C"
void ttn_wait_for_provisioning(void);
/**
* @brief Activates the device via OTAA.
* @brief Activates the device via OTAA using previously provisioned keys.
*
* The DevEUI, AppEUI/JoinEUI and AppKey must have already been provisioned by a call to provision().
* The DevEUI, AppEUI/JoinEUI and AppKey must have already been provisioned by a call
* to @ref ttn_provision() or @ref ttn_provision_with_mac().
* Before this function is called, `nvs_flash_init()` must have been called once.
*
* The RF module is initialized and the TTN background task is started.
*
* The function blocks until the activation has completed or failed.
*
* @return `true` if the activation was succesful, `false` if the activation failed
@ -540,9 +537,12 @@ extern "C"
bool ttn_join_provisioned(void);
/**
* @brief Sets the DevEUI, AppEUI/JoinEUI and AppKey and activate the device via OTAA.
* @brief Activates the device via OTAA using the provided keys.
*
* For the activation, the provided DevEUI, AppEUI/JoinEUI and AppKey are used.
* They are NOT saved in non-volatile memory.
*
* The DevEUI, AppEUI/JoinEUI and AppKey are NOT saved in non-volatile memory.
* The RF module is initialized and the TTN background task is started.
*
* The function blocks until the activation has completed or failed.
*
@ -553,6 +553,65 @@ extern "C"
*/
bool ttn_join(const char *dev_eui, const char *app_eui, const char *app_key);
/**
* @brief Resumes TTN communication after deep sleep.
*
* The communcation state is restored from data previously saved in RTC memory.
* The RF module and the TTN background task are started.
*
* This function is called instead of @ref ttn_join() or @ref ttn_join_provisioned()
* to continue with the established communication and to avoid a further join procedure.
*
* @return `true` if the device was able to resume, `false` otherwise.
*/
bool ttn_resume_after_deep_sleep(void);
/**
* @brief Stops all activies and prepares for deep sleep.
*
* This function is called before entering deep sleep. It saves the current
* communication state in RTC memory and shuts down the RF module and the
* TTN background task.
*
* It neither clears the provisioned keys nor the configured pins
* but they will be lost if the device goes into deep sleep.
*
* Before calling this function, use @ref ttn_busy_duration() to check
* that the TTN device is idle and ready to go to deep sleep.
*
* To restart communication, @ref ttn_resume_after_deep_sleep() must be called.
*/
void ttn_prepare_for_deep_sleep(void);
/**
* @brief Returns the minimum duration the TTN device will be busy.
*
* This function can be called to check whether the TTN device is
* still involved in communication or ready to go to deep sleep or
* to be powered off.
*
* If it returns 0, the TTN communication is idle and the device can go
* to deep sleep or can be powered off.
*
* If it returns a value different from 0, the value indicates the duration
* the device will be certainly busy. After that time, this function must be
* called again. It might still return a value different from 0.
*
* @return busy duration (in FreeRTOS ticks)
*/
TickType_t ttn_busy_duration();
/**
* @brief Stops all activies.
*
* This function shuts down the RF module and the TTN background task. It neither clears the
* provisioned keys nor the configured pins. The currentat device state (and activation)
* are lost.
*
* To restart communication, @ref ttn_join() and @ref ttn_join_provisioned() must be called.
*/
void ttn_shutdown(void);
/**
* @brief Transmits a message
*
@ -642,21 +701,6 @@ extern "C"
*/
void ttn_set_max_tx_pow(int tx_pow);
/**
* @brief Stops all activies and shuts down the RF module and the background tasks.
*
* To restart communication, @ref ttn_startup() and @ref ttn_join() must be called.
* it neither clears the provisioned keys nor the configured pins.
*/
void ttn_shutdown(void);
/**
* @brief Restarts the background tasks and RF module.
*
* This member function must only be called after a call to shutdowna().
*/
void ttn_startup(void);
/**
* @brief Gets current RX/TX window
* @return window

View File

@ -58,6 +58,7 @@ typedef struct
} ttn_lmic_event_t;
static bool is_started;
static bool has_joined;
static QueueHandle_t lmic_event_queue;
static ttn_message_cb message_callback;
static ttn_waiting_reason_t waiting_reason = TTN_WAITING_NONE;
@ -67,6 +68,8 @@ static int subband = 2;
static ttn_data_rate_t join_data_rate = TTN_DR_JOIN_DEFAULT;
static int max_tx_power = DEFAULT_MAX_TX_POWER;
static void start(void);
static void stop(void);
static bool join_core(void);
static void config_rf_params(void);
static void event_callback(void *user_data, ev_t event);
@ -93,16 +96,6 @@ void ttn_configure_pins(spi_host_device_t spi_host, uint8_t nss, uint8_t rxtx, u
#if LMIC_ENABLE_event_logging
ttn_log_init();
#endif
LMIC_registerEventCb(event_callback, NULL);
LMIC_registerRxMessageCb(message_received_callback, NULL);
os_init_ex(NULL);
ttn_reset();
lmic_event_queue = xQueueCreate(4, sizeof(ttn_lmic_event_t));
ASSERT(lmic_event_queue != NULL);
hal_esp32_start_lmic_task();
}
void ttn_set_subband(int band)
@ -110,17 +103,32 @@ void ttn_set_subband(int band)
subband = band;
}
void ttn_reset(void)
void start(void)
{
if (is_started)
return;
LMIC_registerEventCb(event_callback, NULL);
LMIC_registerRxMessageCb(message_received_callback, NULL);
os_init_ex(NULL);
hal_esp32_enter_critical_section();
LMIC_reset();
LMIC_setClockError(MAX_CLOCK_ERROR * 4 / 100);
waiting_reason = TTN_WAITING_NONE;
hal_esp32_leave_critical_section();
lmic_event_queue = xQueueCreate(4, sizeof(ttn_lmic_event_t));
ASSERT(lmic_event_queue != NULL);
hal_esp32_start_lmic_task();
is_started = true;
}
void ttn_shutdown(void)
void stop(void)
{
if (!is_started)
return;
hal_esp32_enter_critical_section();
LMIC_shutdown();
hal_esp32_stop_lmic_task();
@ -128,12 +136,9 @@ void ttn_shutdown(void)
hal_esp32_leave_critical_section();
}
void ttn_startup(void)
void ttn_shutdown(void)
{
hal_esp32_enter_critical_section();
LMIC_reset();
hal_esp32_start_lmic_task();
hal_esp32_leave_critical_section();
stop();
}
bool ttn_provision(const char *dev_eui, const char *app_eui, const char *app_key)
@ -226,7 +231,9 @@ bool join_core(void)
return false;
}
is_started = true;
start();
has_joined = true;
hal_esp32_enter_critical_section();
xQueueReset(lmic_event_queue);
waiting_reason = TTN_WAITING_FOR_JOIN;
@ -239,8 +246,8 @@ bool join_core(void)
ttn_lmic_event_t event;
xQueueReceive(lmic_event_queue, &event, portMAX_DELAY);
is_started = event.event == TTN_EVNT_JOIN_COMPLETED;
return is_started;
has_joined = event.event == TTN_EVNT_JOIN_COMPLETED;
return has_joined;
}
ttn_response_code_t ttn_transmit_message(const uint8_t *payload, size_t length, ttn_port_t port, bool confirm)
@ -317,7 +324,7 @@ void ttn_set_adr_enabled(bool enabled)
void ttn_set_data_rate(ttn_data_rate_t data_rate)
{
if (is_started)
if (has_joined)
{
hal_esp32_enter_critical_section();
LMIC_setDrTxpow(data_rate, LMIC.adrTxPow);
@ -331,7 +338,7 @@ void ttn_set_data_rate(ttn_data_rate_t data_rate)
void ttn_set_max_tx_pow(int tx_pow)
{
if (is_started)
if (has_joined)
{
hal_esp32_enter_critical_section();
LMIC_setDrTxpow(LMIC.datarate, tx_pow);