made MQTT broker IP configurable via shell,

implemented storing the IP to NVS and retrieving it on startup
main
Jonas Arnold 4 years ago
parent 71f37109f4
commit 5f3f348b90
  1. 2
      ADIS_ESP32_Eclipse/main/Shell.c
  2. 258
      ADIS_ESP32_Eclipse/main/challenge_nvs.c
  3. 18
      ADIS_ESP32_Eclipse/main/challenge_nvs.h
  4. 64
      ADIS_ESP32_Eclipse/main/myMqtt.c
  5. 14
      ADIS_ESP32_Eclipse/main/myMqtt.h

@ -43,6 +43,7 @@
#include "driver/gpio.h"
#if PL_CONFIG_CHALLENGE_APP_ACTIVATED
#include "challenge_app.h"
#include "myMqtt.h"
#endif
#define SHELL_ESP32_UART_DEVICE (UART_NUM_0) /* Uart for bootloader and connection to robot */
@ -80,6 +81,7 @@ static const McuShell_ParseCommandCallback CmdParserTable[] =
#endif
#if PL_CONFIG_CHALLENGE_APP_ACTIVATED
Challenge_ParseShellCommand,
MyMqtt_ParseShellCommand,
#endif
NULL /* Sentinel */
};

@ -10,19 +10,32 @@
#include "esp_system.h"
#include "nvs_flash.h"
#include "nvs.h"
#include "McuUtility.h"
#include "freertos/FreeRTOS.h"
#include "freertos/semphr.h"
/* defines / constants */
#define TAG "CHALLENGE_NVS" /* tag for logging with ESP_LOG */
const char* NAMESPACE_NVS = "storage";
const char* ROBOT_MODE_KEY = "robot_mode";
const char* MQTT_IP_KEY = "mqtt_ip";
/* local vars */
bool initializedSuccessfully = false;
SemaphoreHandle_t semaphore = NULL;
/*! \brief Initialize the NVS storage. */
void Challenge_Nvs_Init(void){
ESP_LOGI(TAG, "Initializing...");
// initialize semaphore
semaphore = xSemaphoreCreateRecursiveMutex();
if(semaphore == NULL){
ESP_LOGE(TAG, "Failed to initialize semaphore for Challenge NVS!");
}else{
vQueueAddToRegistry(semaphore, "challenge_nvs_semphr");
}
// Initialize NVS
esp_err_t err = nvs_flash_init();
if (err == ESP_ERR_NVS_NO_FREE_PAGES || err == ESP_ERR_NVS_NEW_VERSION_FOUND) {
@ -42,97 +55,206 @@ void Challenge_Nvs_Deinit(void){
ESP_LOGI(TAG, "Deinitializing...");
esp_err_t err = nvs_flash_deinit();
ESP_LOGI(TAG, "Deinitialized. Success=%s", err==ESP_OK?"true":"false");
vSemaphoreDelete(semaphore);
}
/* HELPERS FOR SEMAPHORE */
static bool Challenge_Nvs_AquireMutex(void){
if(xSemaphoreTakeRecursive(semaphore, pdMS_TO_TICKS(100)) != pdTRUE){
/* timeout */
ESP_LOGW(TAG, "Timemout while aquiring challenge NVS semaphore.");
return false;
}
return true;
}
static void Challenge_Nvs_ReleaseMutex(void){
xSemaphoreGive(semaphore);
}
/*!
* \brief Stores the passed robot mode in NVS.
* \param modeStationary Mode to store. True = stationary mode, False = mobile mode
* \return true on success
*/
bool Challenge_Nvs_StoreRobotModeToNVS(bool mode){
bool success = false;
// Open
ESP_LOGI(TAG, "Opening Non-Volatile Storage (NVS) handle... ");
nvs_handle_t my_handle;
esp_err_t err = nvs_open(NAMESPACE_NVS, NVS_READWRITE, &my_handle);
if (err != ESP_OK) {
ESP_LOGE(TAG, "Error (%s) opening NVS handle!\n", esp_err_to_name(err));
return false;
}
if(Challenge_Nvs_AquireMutex()){
// Open
ESP_LOGI(TAG, "Opening Non-Volatile Storage (NVS) handle... ");
nvs_handle_t my_handle;
esp_err_t err = nvs_open(NAMESPACE_NVS, NVS_READWRITE, &my_handle);
if (err != ESP_OK) {
ESP_LOGE(TAG, "Error (%s) opening NVS handle!\n", esp_err_to_name(err));
return false;
}
// Write
uint8_t value = mode?1:0;
ESP_LOGI(TAG, "Updating robotMode in NVS ... ");
err = nvs_set_u8(my_handle, ROBOT_MODE_KEY, value);
if(err != ESP_OK){
ESP_LOGE(TAG, "Failed to update robotMode in NVS. Error=(%s)", esp_err_to_name(err));
success = false;
}else{ // successfully set
// Commit written value.
// After setting any values, nvs_commit() must be called to ensure changes are written
// to flash storage. Implementations may write to storage at other times,
// but this is not guaranteed.
ESP_LOGI(TAG, "Committing updates in NVS ... ");
err = nvs_commit(my_handle);
// Write
uint8_t value = mode?1:0;
ESP_LOGI(TAG, "Updating robotMode in NVS ... ");
err = nvs_set_u8(my_handle, ROBOT_MODE_KEY, value);
if(err != ESP_OK){
ESP_LOGE(TAG, "Failed to commit to NVS. Error=(%s)", esp_err_to_name(err));
ESP_LOGE(TAG, "Failed to update robotMode in NVS. Error=(%s)", esp_err_to_name(err));
success = false;
}else{
ESP_LOGI(TAG, "Successfully committed changes to NVS.");
success = true;
}else{ // successfully set
// Commit written value.
// After setting any values, nvs_commit() must be called to ensure changes are written
// to flash storage. Implementations may write to storage at other times,
// but this is not guaranteed.
ESP_LOGI(TAG, "Committing updates in NVS ... ");
err = nvs_commit(my_handle);
if(err != ESP_OK){
ESP_LOGE(TAG, "Failed to commit to NVS. Error=(%s)", esp_err_to_name(err));
success = false;
}else{
ESP_LOGI(TAG, "Successfully committed changes to NVS.");
success = true;
}
}
}
// Close
nvs_close(my_handle);
// Close
nvs_close(my_handle);
Challenge_Nvs_ReleaseMutex();
}
return success;
}
/*!
* \brief Retrieve the robot mode stored in NVS.
* \param mode Pointer to the location where to retrieve the mode to. True = stationary mode, False = mobile mode
* \return true on success
*/
bool Challenge_Nvs_GetRobotModeFromNVS(bool *mode){
bool success = false;
bool notInitialized = false;
// Open
ESP_LOGI(TAG, "Opening Non-Volatile Storage (NVS) handle... ");
nvs_handle_t my_handle;
esp_err_t err = nvs_open(NAMESPACE_NVS, NVS_READWRITE, &my_handle);
if (err != ESP_OK) {
ESP_LOGE(TAG, "Error (%s) opening NVS handle!\n", esp_err_to_name(err));
return false;
}
// Read
ESP_LOGI(TAG, "Reading robot mode from NVS ... ");
uint8_t value = 0;
err = nvs_get_u8(my_handle, ROBOT_MODE_KEY, &value);
switch (err) {
case ESP_OK:
ESP_LOGI(TAG, "Reading robot mode done. Read robotMode = %i", value);
*mode = (bool)(value==1?true:false); // set value at pointer location
success = true;
break;
case ESP_ERR_NVS_NOT_FOUND:
ESP_LOGI(TAG, "Reading robot mode done. The value is not initialized yet!");
notInitialized = true;
break;
default :
ESP_LOGI(TAG, "Error reading robot mode. Error=(%s)", esp_err_to_name(err));
if(Challenge_Nvs_AquireMutex()){
// Open
ESP_LOGI(TAG, "Opening Non-Volatile Storage (NVS) handle... ");
nvs_handle_t my_handle;
esp_err_t err = nvs_open(NAMESPACE_NVS, NVS_READWRITE, &my_handle);
if (err != ESP_OK) {
ESP_LOGE(TAG, "Error (%s) opening NVS handle!\n", esp_err_to_name(err));
return false;
}
// Read
ESP_LOGI(TAG, "Reading robot mode from NVS ... ");
uint8_t value = 0;
err = nvs_get_u8(my_handle, ROBOT_MODE_KEY, &value);
switch (err) {
case ESP_OK:
ESP_LOGI(TAG, "Reading robot mode done. Read robotMode = %i", value);
*mode = (bool)(value==1?true:false); // set value at pointer location
success = true;
break;
case ESP_ERR_NVS_NOT_FOUND:
ESP_LOGI(TAG, "Reading robot mode done. The value is not initialized yet!");
notInitialized = true;
break;
default :
ESP_LOGI(TAG, "Error reading robot mode. Error=(%s)", esp_err_to_name(err));
success = false;
}
// Close
nvs_close(my_handle);
if(notInitialized){
success = Challenge_Nvs_StoreRobotModeToNVS(false); // initialize to false
}
Challenge_Nvs_ReleaseMutex();
}
return success;
}
bool Challenge_Nvs_StoreBrokerIpToNVS(char* ip){
bool success = false;
if(Challenge_Nvs_AquireMutex()){
// Open
ESP_LOGI(TAG, "Opening Non-Volatile Storage (NVS) handle... ");
nvs_handle_t my_handle;
esp_err_t err = nvs_open(NAMESPACE_NVS, NVS_READWRITE, &my_handle);
if (err != ESP_OK) {
ESP_LOGE(TAG, "Error (%s) opening NVS handle!\n", esp_err_to_name(err));
return false;
}
// Write
ESP_LOGI(TAG, "Updating mqtt broker IP in NVS ... ");
err = nvs_set_str(my_handle, MQTT_IP_KEY, ip);
if(err != ESP_OK){
ESP_LOGE(TAG, "Failed to update mqtt broker IP in NVS. Error=(%s)", esp_err_to_name(err));
success = false;
}else{ // successfully set
// Commit written value.
// After setting any values, nvs_commit() must be called to ensure changes are written
// to flash storage. Implementations may write to storage at other times,
// but this is not guaranteed.
ESP_LOGI(TAG, "Committing updates in NVS ... ");
err = nvs_commit(my_handle);
if(err != ESP_OK){
ESP_LOGE(TAG, "Failed to commit to NVS. Error=(%s)", esp_err_to_name(err));
success = false;
}else{
ESP_LOGI(TAG, "Successfully committed changes to NVS.");
success = true;
}
}
// Close
nvs_close(my_handle);
Challenge_Nvs_ReleaseMutex();
}
// Close
nvs_close(my_handle);
return success;
}
bool Challenge_Nvs_GetBrokerIpFromNVS(char *ip, size_t length){
bool success = false;
bool notInitialized = false;
if(Challenge_Nvs_AquireMutex()){
// Open
ESP_LOGI(TAG, "Opening Non-Volatile Storage (NVS) handle... ");
nvs_handle_t my_handle;
esp_err_t err = nvs_open(NAMESPACE_NVS, NVS_READWRITE, &my_handle);
if (err != ESP_OK) {
ESP_LOGE(TAG, "Error (%s) opening NVS handle!\n", esp_err_to_name(err));
return false;
}
if(notInitialized){
success = Challenge_Nvs_StoreRobotModeToNVS(false); // initialize to false
// Read
ESP_LOGI(TAG, "Reading mqtt broker IP from NVS ... ");
size_t required_size;
nvs_get_str(my_handle, MQTT_IP_KEY, NULL, &required_size); // retrieve required size
char* value = pvPortMalloc(required_size);
err = nvs_get_str(my_handle, MQTT_IP_KEY, value, &required_size);
switch (err) {
case ESP_OK:
ESP_LOGI(TAG, "Reading mqtt broker ip done. Read IP = %s", value);
McuUtility_strcpy((unsigned char*)ip, length, (unsigned char *)value); // copy ip to destination
ESP_LOGI(TAG, "Copied mqtt broker ip. ip=%s", ip);
success = true;
break;
case ESP_ERR_NVS_NOT_FOUND:
ESP_LOGI(TAG, "Reading mqtt broker ip done. The value is not initialized yet!");
notInitialized = true;
break;
default :
ESP_LOGI(TAG, "Error reading mqtt broker ip. Error=(%s)", esp_err_to_name(err));
success = false;
}
// Close
nvs_close(my_handle);
if(notInitialized){
success = Challenge_Nvs_StoreBrokerIpToNVS("10.0.1.1"); // initialize to default IP
}
Challenge_Nvs_ReleaseMutex();
}
return success;
}

@ -9,6 +9,7 @@
#define MAIN_CHALLENGE_NVS_H_
#include <stdbool.h>
#include <stddef.h>
/*! \brief Initialize the NVS storage. */
void Challenge_Nvs_Init(void);
@ -18,7 +19,7 @@ void Challenge_Nvs_Deinit(void);
/*!
* \brief Stores the passed robot mode in NVS.
* \param modeStationary Mode to store. True = stationary mode, False = mobile mode
* \param mode Stationary Mode to store. True = stationary mode, False = mobile mode
* \return true on success
*/
bool Challenge_Nvs_StoreRobotModeToNVS(bool mode);
@ -30,4 +31,19 @@ bool Challenge_Nvs_StoreRobotModeToNVS(bool mode);
*/
bool Challenge_Nvs_GetRobotModeFromNVS(bool *mode);
/*!
* \brief Stores the passed MQTT Broker IP in NVS.
* \param ip IP to store.
* \return true on success
*/
bool Challenge_Nvs_StoreBrokerIpToNVS(char* ip);
/*!
* \brief Retrieve the MQTT Broker IP stored in NVS. If the Broker IP is not yet stored in NVS, it will be initially stored as "10.0.0.1".
* \param ip Pointer to the location where to store the retrieved the IP to.
* \param length Size of the array ip.
* \return true on success
*/
bool Challenge_Nvs_GetBrokerIpFromNVS(char *ip, size_t length);
#endif /* MAIN_CHALLENGE_NVS_H_ */

@ -12,13 +12,15 @@
#include "esp_log.h"
#include "mqtt_client.h"
#include "challenge_com.h"
// Settings
#define CONFIG_BROKER_URL "mqtt://10.180.254.80"
#include "challenge_nvs.h"
#include "McuUtility.h"
// tag for logging with ESP_LOG
static const char *TAG = "MY_MQTT";
// local cars
char _brokerIp[] = "255.255.255.255"; // max length of ip
// declarations
static void log_error_if_nonzero(const char *message, int error_code);
static void mqtt_event_handler(void *handler_args, esp_event_base_t base, int32_t event_id, void *event_data);
@ -27,8 +29,15 @@ static void mqtt_event_handler(void *handler_args, esp_event_base_t base, int32_
esp_mqtt_client_handle_t client;
bool MyMqtt_Init(void){
char brokerUri[50];
// get from NVS
Challenge_Nvs_GetBrokerIpFromNVS(_brokerIp, sizeof(_brokerIp));
ESP_LOGI(TAG, "Got Broker IP '%s' from NVS", _brokerIp);
McuUtility_strcpy((unsigned char*)brokerUri, sizeof(brokerUri), (unsigned char*)"mqtt://");
McuUtility_strcat((unsigned char*)brokerUri, sizeof(brokerUri), (unsigned char*)_brokerIp);
ESP_LOGI(TAG, "Connecting to Mqtt Broker URI '%s'", brokerUri);
esp_mqtt_client_config_t mqtt_cfg = {
.uri = CONFIG_BROKER_URL,
.uri = brokerUri,
};
client = esp_mqtt_client_init(&mqtt_cfg);
/* The last argument may be used to pass data to the event handler, in this example mqtt_event_handler */
@ -56,6 +65,18 @@ void MyMqtt_Subscribe(const char *topic){
ESP_LOGI(TAG, "sent subscribe successful, msg_id=%d, success=%s", msg_id, msg_id==-1 ? "false" : "true");
}
char* MyMqtt_GetBrokerIP(void){
return _brokerIp;
}
void MyMqtt_SetBrokerIP(char* ip){
ESP_LOGI(TAG, "Set Broker IP to '%s'", ip);
McuUtility_strcpy((unsigned char*)_brokerIp, sizeof(_brokerIp), (unsigned char*)ip);
// store to NVS
Challenge_Nvs_StoreBrokerIpToNVS(_brokerIp);
}
/***********/
/* HELPERS */
/***********/
@ -124,3 +145,38 @@ static void mqtt_event_handler(void *handler_args, esp_event_base_t base, int32_
break;
}
}
/*********/
/* SHELL */
/*********/
#if PL_CONFIG_USE_SHELL
static uint8_t PrintStatus(const McuShell_StdIOType *io) {
McuShell_SendStatusStr((unsigned char*)"mqtt", (unsigned char*)"ESP32 MQTT status\r\n", io->stdOut);
McuShell_SendStatusStr((unsigned char*)" ip", (unsigned char*)MyMqtt_GetBrokerIP(), io->stdOut);
return ERR_OK;
}
static uint8_t PrintHelp(const McuShell_StdIOType *io) {
McuShell_SendHelpStr((unsigned char*)"mqtt", (unsigned char*)"Group of ESP32 MQTT commands\r\n", io->stdOut);
McuShell_SendHelpStr((unsigned char*)" help|status", (unsigned char*)"Shows MQTT help or status\r\n", io->stdOut);
McuShell_SendHelpStr((unsigned char*)" setIp <ipv4>", (unsigned char*)"Sets the IP address of the MQTT broker\r\n", io->stdOut);
return ERR_OK;
}
uint8_t MyMqtt_ParseShellCommand(const unsigned char* cmd, bool *handled, const McuShell_StdIOType *io) {
if (McuUtility_strcmp((char*)cmd, (char*)McuShell_CMD_HELP)==0 || McuUtility_strcmp((char*)cmd, (char*)"mqtt help")==0) {
*handled = TRUE;
return PrintHelp(io);
} else if (McuUtility_strcmp((char*)cmd, (char*)McuShell_CMD_STATUS)==0 || McuUtility_strcmp((char*)cmd, (char*)"mqtt status")==0) {
*handled = TRUE;
return PrintStatus(io);
} else if (McuUtility_strncmp((char*)cmd,"mqtt setIp",sizeof("mqtt setIp")-1) == 0) { // contains
*handled = TRUE;
char ip[] = "255.255.255.255"; // maximum size of IP
McuUtility_strcpy((unsigned char*)ip, sizeof(ip), (unsigned char *)cmd + strlen((char*)"mqtt setIp ")); // cut front
McuUtility_strCutTail((unsigned char*)ip, (unsigned char*)"\0\0\0"); // cut tail
MyMqtt_SetBrokerIP(ip); // set ip
}
return ERR_OK;
}
#endif /* PL_CONFIG_USE_SHELL */

@ -8,6 +8,7 @@
#ifndef MAIN_MYMQTT_H_
#define MAIN_MYMQTT_H_
#include "platform.h"
#include <stdbool.h>
bool MyMqtt_Init(void);
@ -18,4 +19,17 @@ void MyMqtt_Publish(const char *topic, const char *data);
void MyMqtt_Subscribe(const char *topic);
#if PL_CONFIG_USE_SHELL
#include "McuShell.h"
/*!
* \brief Command line and shell handler
* \param cmd The command to be parsed
* \param handled If command has been recognized and handled
* \param io I/O handler to be used
* \return error code, otherwise ERR_OK
*/
uint8_t MyMqtt_ParseShellCommand(const unsigned char* cmd, bool *handled, const McuShell_StdIOType *io);
#endif
#endif /* MAIN_MYMQTT_H_ */

Loading…
Cancel
Save